import { Config, Context, Effect, Logger as EffectLogger, Layer, Ref, type Scope } from "effect"; import { type DailyFileSinkOptions } from "./sinks.js"; import { type LogHook, type LogItem, LogLevel, type LogSink, type LogSinkInput, type LogTap } from "./types.js"; /** Annotation key the Effect logger adapter reads as the logger name. */ export declare const LOGGER_ANNOTATION = "logger"; /** * True inside a hook or tap fiber. A log call made from there (a tap that * persists lines through `Entity.upsert`, which itself logs) still prints and * is captured, but does not re-run the tap or hooks; without this guard every * such line would fork another hook fiber forever. */ export declare const InsideLogHook: Context.Reference; /** * A logger bound to a name. Pure to create (`Logger.named("Main")`); every * method is an `Effect` that requires the `Logger` service. */ export interface NamedLogger { readonly name: string; /** The channel every item from this logger carries, or undefined for the default channel. */ readonly channelName: string | undefined; /** A child logger named `${name}:${child}` (or the same name when `null`), on the same channel. */ extend(child: string | null): NamedLogger; /** * The same logger emitting on `channel` (see `LogItem.channel`): a sink * such as `channelSink(toast, "attention")` picks those lines out while * every other sink still records them. `null` returns to the default channel. */ channel(channel: string | null): NamedLogger; log(level: LogLevel, message: string, ...args: unknown[]): Effect.Effect; debug(message: string, ...args: unknown[]): Effect.Effect; info(message: string, ...args: unknown[]): Effect.Effect; warn(message: string, ...args: unknown[]): Effect.Effect; error(message: string, ...args: unknown[]): Effect.Effect; } /** The service behind every `NamedLogger` and behind `Effect.log*` (via the adapter). */ export interface LoggerShape { /** Threshold below which items reach no sink; the tap still sees everything. */ readonly level: LogLevel; /** Emits one log item: tap, threshold, sinks (in order), hooks. */ emit(item: LogItem): Effect.Effect; /** * `emit` for synchronous callers (Effect's own `Logger.log` contract). Runs * in a fiber tracked by `flush`; the synchronous part (console, capture) * completes before this returns unless the tap suspends. `insideHook` is the * caller's `InsideLogHook` value. After the layer's scope has closed the * item is written straight to the console instead of being dropped. */ emitUnsafe(item: LogItem, insideHook?: boolean): void; /** Waits for every hook fiber started so far and for every sink's buffer. Run before process exit. */ readonly flush: Effect.Effect; } export interface LoggerOptions { /** Sink threshold. Defaults to `LogLevel.INFO`. */ readonly level?: LogLevel; /** * Where lines at or above `level` go, in order. Defaults to the console * (`Logger.consoleSink`); pass an explicit list to add or replace it, e.g. * `[Logger.consoleSink, Logger.dailyFileSink({ directory, prefix })]`. */ readonly sinks?: ReadonlyArray>; /** Called on every `error` log. Pair with `Pushover.logHook` to keep the old default. */ readonly onError?: LogHook; /** Called on every `warn` log. */ readonly onWarn?: LogHook; /** Sees every log call regardless of `level`. */ readonly onLog?: LogTap; } declare const CapturedLogs_base: Context.ServiceClass>; /** Every log item emitted through `Logger.layerCapture`, in order. */ export declare class CapturedLogs extends CapturedLogs_base { } declare const Logger_base: Context.ServiceClass; /** * The logging service: hierarchical named loggers with a console threshold, * warn/error notification hooks with flush tracking, and a global tap. * * `Effect.log*` calls reach the same sink through `Logger.layerAdapter`. */ export declare class Logger extends Logger_base { /** A named logger. Pure; the effects it returns require `Logger`. */ static named(name: string): NamedLogger; /** Waits for every pending hook fiber. Run before process exit or a Lambda return. */ static readonly flush: Effect.Effect; /** The given sinks (default: console) with the threshold, hooks and tap. */ static layer(options?: LoggerOptions): Layer.Layer; /** * `Logger.layer` with the threshold read from `LOG_LEVEL` (debug | info | * warn | error; default info) through the configured `ConfigProvider`. */ static layerConfig(options?: Omit, "level">): Layer.Layer; /** * Records items at or above `level` into `CapturedLogs` instead of printing * them (hooks, the tap and any extra `sinks` still run exactly as with * `layer`). For tests: read with `Logger.captured`. */ static layerCapture(options?: LoggerOptions): Layer.Layer; /** Every item captured so far by `Logger.layerCapture`. */ static readonly captured: Effect.Effect, never, CapturedLogs>; /** Drops everything captured so far. */ static readonly clearCaptured: Effect.Effect; /** * An Effect `Logger` that forwards `Effect.log*` into this service. The * logger name is taken from the `logger` log annotation (see * `Effect.annotateLogs`), falling back to "effect". */ static readonly effectLogger: Effect.Effect, never, Logger>; /** * Routes `Effect.log*` into the `Logger` service and lifts Effect's own * minimum log level to `All` so the sink (and the tap) sees every call; * the sink applies the configured threshold to console output. */ static readonly layerAdapter: Layer.Layer; /** The default sink: the Effect `Console` service. */ static readonly consoleSink: Effect.Effect; /** One file per local day with retention; see `dailyFileSink` in `./sinks`. */ static dailyFileSink(options: DailyFileSinkOptions): Effect.Effect; /** * A `Tracer` that writes every ended `Effect.fn` / `Effect.withSpan` span * to this logger at debug: name, duration, parent and outcome. Provide it * alongside `layer`; nothing else consumes the span names otherwise. */ static readonly layerTracer: Layer.Layer; } export {};