Logger.ts
Logger.ts overview
Section titled “Logger.ts overview”Defines loggers and log-event data for Effect programs.
A Logger<Message, Output> receives each log event as Options and turns it
into output such as a formatted string, structured object, console write,
file write, JSON line, or trace span event. This module also includes active
logger references, console routing helpers, built-in formatters, batching,
file logging, and layers for installing loggers.
Since v2.0.0
Exports Grouped by Category
Section titled “Exports Grouped by Category”constructors
Section titled “constructors”batched
Section titled “batched”Creates a scoped logger that batches the output of another logger.
Details
The returned effect starts a scoped background process that periodically
passes buffered outputs to flush. When the scope closes, the background
process is interrupted and any remaining buffered entries are flushed.
Example (Batching logger output)
import { Duration, Effect, Logger } from "effect"
// Create a batched logger that flushes every 5 secondsconst batchedLogger = Logger.batched(Logger.formatJson, { window: Duration.seconds(5), flush: (messages) => Effect.sync(() => { console.log(`Flushing ${messages.length} log entries:`) messages.forEach((msg, i) => console.log(`${i + 1}. ${msg}`)) })})
const program = Effect.gen(function* () { const logger = yield* batchedLogger
yield* Effect.provide( Effect.all([ Effect.log("Event 1"), Effect.log("Event 2"), Effect.log("Event 3"), Effect.sleep(Duration.seconds(6)), // Trigger flush Effect.log("Event 4") ]), Logger.layer([logger]) )})
// Remote batch logging exampleconst remoteBatchLogger = Logger.batched(Logger.formatStructured, { window: Duration.seconds(10), flush: (entries) => Effect.sync(() => { // Send batch to remote logging service console.log(`Sending ${entries.length} log entries to remote service`) })})Signature
declare const batched: (<Output>(options: { readonly window: Duration.Input readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>}) => <Message>(self: Logger<Message, Output>) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>) & (<Message, Output>( self: Logger<Message, Output>, options: { readonly window: Duration.Input readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void> } ) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>)Since v2.0.0
consoleJson
Section titled “consoleJson”A Logger which outputs logs using a structured format serialized as JSON
on a single line and writes them to the console.
Details
For example, console JSON output can render as
{"message":["hello"],"level":"INFO","timestamp":"2025-01-03T14:28:57.508Z", "annotations":{"key":"value"},"spans":{"label":0},"fiberId":"#1"}.
Example (Logging JSON output to the console)
import { Effect, Logger } from "effect"
// Use the console JSON loggerconst jsonProgram = Effect.log("Hello JSON Console").pipe(Effect.provide(Logger.layer([Logger.consoleJson])))
// Perfect for production logging and log aggregationconst productionProgram = Effect.gen(function* () { yield* Effect.log("Server started", { port: 3000, env: "production" }) yield* Effect.logInfo("Request", { method: "POST", url: "/api/users", body: { name: "Alice" } }) yield* Effect.logError("Database error", { error: "Connection timeout", retryCount: 3 })}).pipe( Effect.annotateLogs("service", "user-api"), Effect.annotateLogs("version", "1.2.3"), Effect.withLogSpan("request-processing"), Effect.provide(Logger.layer([Logger.consoleJson])))
// Easy to pipe to log aggregation servicesconst productionSetup = Logger.layer([ Logger.consoleJson, // For stdout JSON logs Logger.consolePretty() // For local debugging])
// Ideal for containerized environments (Docker, Kubernetes)const containerProgram = Effect.log("Container ready", { containerId: "abc123", image: "myapp:latest"}).pipe(Effect.provide(Logger.layer([Logger.consoleJson])))Signature
declare const consoleJson: Logger<unknown, void>Since v4.0.0
consoleLogFmt
Section titled “consoleLogFmt”A Logger which outputs logs using the logfmt
style and writes them to the console.
Details
For example, a console logfmt entry is rendered as
timestamp=2025-01-03T14:22:47.570Z level=INFO fiber=#1 message=info.
Example (Logging logfmt output to the console)
import { Effect, Logger } from "effect"
// Use the console logfmt loggerconst logfmtProgram = Effect.log("Hello LogFmt Console").pipe(Effect.provide(Logger.layer([Logger.consoleLogFmt])))
// Great for production environmentsconst productionProgram = Effect.gen(function* () { yield* Effect.log("Server started", { port: 8080, version: "1.0.0" }) yield* Effect.logInfo("Request processed", { userId: 123, duration: 45 }) yield* Effect.logError("Validation failed", { field: "email", value: "invalid" })}).pipe( Effect.annotateLogs("service", "api"), Effect.withLogSpan("request-handler"), Effect.provide(Logger.layer([Logger.consoleLogFmt])))
// Combine with other loggersconst multiLoggerLive = Logger.layer([Logger.consoleLogFmt, Logger.consolePretty()])Signature
declare const consoleLogFmt: Logger<unknown, void>Since v4.0.0
consolePretty
Section titled “consolePretty”A Logger which outputs logs in a “pretty” format and writes them to the
console.
Details
For example, pretty output can render as
[09:37:17.579] INFO (#1) label=0ms: hello followed by an annotation line
such as key: value.
Example (Logging with pretty console output)
import { Effect, Logger } from "effect"
// Use the pretty console logger with default settingsconst basicPretty = Effect.log("Hello Pretty Format").pipe(Effect.provide(Logger.layer([Logger.consolePretty()])))
// Configure pretty logger optionsconst customPretty = Logger.consolePretty({ colors: true, stderr: false, mode: "tty", formatDate: (date) => date.toLocaleTimeString()})
// Perfect for development environmentconst developmentProgram = Effect.gen(function* () { yield* Effect.log("Application starting") yield* Effect.logInfo("Database connected") yield* Effect.logWarning("High memory usage detected")}).pipe( Effect.annotateLogs("environment", "development"), Effect.withLogSpan("startup"), Effect.provide(Logger.layer([customPretty])))
// Disable colors for CI/CD environmentsconst ciLogger = Logger.consolePretty({ colors: false })Signature
declare const consolePretty: (options?: { readonly colors?: "auto" | boolean | undefined readonly stderr?: boolean | undefined readonly formatDate?: ((date: Date) => string) | undefined readonly mode?: "browser" | "tty" | "auto" | undefined}) => Logger<unknown, void>Since v4.0.0
consoleStructured
Section titled “consoleStructured”A Logger which outputs logs using a structured format and writes them to
the console.
Details
For example, console structured output can contain
message: [ "info", "message" ], level: "INFO",
timestamp: "2025-01-03T14:25:39.666Z",
annotations: { key: "value" }, spans: { label: 0 }, and
fiberId: "#1".
Example (Logging structured output to the console)
import { Effect, Logger } from "effect"
// Use the console structured loggerconst structuredProgram = Effect.log("Hello Structured Console").pipe( Effect.provide(Logger.layer([Logger.consoleStructured])))
// Perfect for development debuggingconst debugProgram = Effect.gen(function* () { yield* Effect.log("User event", { userId: 123, action: "login", ip: "192.168.1.1" }) yield* Effect.logInfo("API call", { endpoint: "/users", method: "GET", duration: 120 })}).pipe( Effect.annotateLogs("requestId", "req-123"), Effect.withLogSpan("authentication"), Effect.provide(Logger.layer([Logger.consoleStructured])))
// Easy to parse and inspect object structureconst inspectionProgram = Effect.gen(function* () { yield* Effect.log("Complex data", { user: { id: 1, name: "John" }, metadata: { source: "api", version: 2 } })}).pipe(Effect.provide(Logger.layer([Logger.consoleStructured])))Signature
declare const consoleStructured: Logger<unknown, void>Since v4.0.0
defaultLogger
Section titled “defaultLogger”The default logging implementation used by the Effect runtime.
Example (Referencing the default logger)
import { Effect, Logger } from "effect"
// Use the default logger (automatically used by Effect runtime)const program = Effect.gen(function* () { yield* Effect.log("This uses the default logger") yield* Effect.logInfo("Info message") yield* Effect.logError("Error message")})
// Explicitly use the default loggerconst withDefaultLogger = Effect.log("Explicit default").pipe(Effect.provide(Logger.layer([Logger.defaultLogger])))
// Compare with custom loggerconst customLogger = Logger.make((options) => { console.log(`CUSTOM: ${options.message}`)})Signature
declare const defaultLogger: Logger<unknown, void>Since v2.0.0
formatJson
Section titled “formatJson”A Logger which outputs logs using a structured format serialized as JSON
on a single line.
Details
For example, a JSON entry can render as {"message":["hello"],"level":"INFO", "timestamp":"2025-01-03T14:28:57.508Z","annotations":{"key":"value"}, "spans":{"label":0},"fiberId":"#1"}.
Example (Formatting logs as JSON)
import { Effect, Logger } from "effect"
// Use the JSON format loggerconst jsonLoggerProgram = Effect.log("Hello JSON Format").pipe(Effect.provide(Logger.layer([Logger.formatJson])))
// Perfect for log aggregation and processing systemsconst productionProgram = Effect.gen(function* () { yield* Effect.log("Server started", { port: 3000, env: "production" }) yield* Effect.logInfo("Request received", { method: "GET", path: "/api/users" }) yield* Effect.logError("Database error", { error: "Connection timeout" })}).pipe( Effect.annotateLogs("service", "api-server"), Effect.withLogSpan("request-processing"), Effect.provide(Logger.layer([Logger.formatJson])))
// Adapt the JSON string before giving it to an output sinkconst envelopedJsonLogger = Logger.map( Logger.formatJson, (jsonString) => `{"service":"api-server","entry":${jsonString}}`)
const envelopedConsoleLogger = Logger.withConsoleLog(envelopedJsonLogger)Signature
declare const formatJson: Logger<unknown, string>Since v4.0.0
formatLogFmt
Section titled “formatLogFmt”A Logger which outputs logs using the logfmt
style.
Details
For example, a logfmt entry is rendered as
timestamp=2025-01-03T14:22:47.570Z level=INFO fiber=#1 message=hello.
Example (Formatting logs as logfmt)
import { Effect, Logger } from "effect"
// Use the logfmt format loggerconst logfmtLoggerProgram = Effect.log("Hello LogFmt Format").pipe(Effect.provide(Logger.layer([Logger.formatLogFmt])))
// Perfect for structured logging systemsconst structuredProgram = Effect.gen(function* () { yield* Effect.log("User login", { userId: 123, method: "OAuth" }) yield* Effect.logInfo("Request processed", { duration: 45, status: "success" })}).pipe(Effect.provide(Logger.layer([Logger.withConsoleLog(Logger.formatLogFmt)])))
// Good for log aggregation systems like Splunk, ELKconst productionLogger = Logger.formatLogFmtSignature
declare const formatLogFmt: Logger<unknown, string>Since v4.0.0
formatSimple
Section titled “formatSimple”A Logger which outputs logs as a string.
Details
For example, a simple log entry is rendered as
timestamp=2025-01-03T14:22:47.570Z level=INFO fiber=#1 message=hello.
Example (Formatting logs as simple strings)
import { Effect, Logger } from "effect"
// Use the simple format loggerconst simpleLoggerProgram = Effect.log("Hello Simple Format").pipe(Effect.provide(Logger.layer([Logger.formatSimple])))
// Combine with console outputconst consoleSimpleLogger = Logger.withConsoleLog(Logger.formatSimple)
const program = Effect.gen(function* () { yield* Effect.log("Application started") yield* Effect.logInfo("Processing data") yield* Effect.logWarning("Memory usage high")}).pipe(Effect.provide(Logger.layer([consoleSimpleLogger])))Signature
declare const formatSimple: Logger<unknown, string>Since v4.0.0
formatStructured
Section titled “formatStructured”A Logger which outputs logs using a structured format.
Details
For example, a structured entry can contain message: [ "hello" ],
level: "INFO", timestamp: "2025-01-03T14:25:39.666Z",
annotations: { key: "value" }, spans: { label: 0 }, and
fiberId: "#1".
Example (Formatting logs as structured objects)
import { Effect, Logger } from "effect"
// Use the structured format loggerconst structuredLoggerProgram = Effect.log("Hello Structured Format").pipe( Effect.provide(Logger.layer([Logger.formatStructured])))
// Perfect for JSON processing and analyticsconst analyticsProgram = Effect.gen(function* () { yield* Effect.log("User action", { action: "click", element: "button" }) yield* Effect.logInfo("API call", { endpoint: "/users", duration: 150 })}).pipe( Effect.annotateLogs("sessionId", "abc123"), Effect.withLogSpan("request"), Effect.provide(Logger.layer([Logger.formatStructured])))
// Process structured outputconst processingLogger = Logger.map(Logger.formatStructured, (output) => { // Process the structured object const enhanced = { ...output, processed: true } return enhanced})Signature
declare const formatStructured: Logger< unknown, { readonly level: string readonly fiberId: string readonly timestamp: string readonly message: unknown readonly cause: string | undefined readonly annotations: Record<string, unknown> readonly spans: Record<string, number> }>Since v4.0.0
Creates a new Logger from a log function.
Details
The log function receives an options object containing the message, log level, cause, fiber information, and timestamp, and should return the desired output.
Example (Creating loggers from functions)
import { Effect, Logger, References } from "effect"
// Simple text loggerconst textLogger = Logger.make((options) => `${options.date.toISOString()} [${options.logLevel}] ${options.message}`)
// Structured object loggerconst objectLogger = Logger.make((options) => ({ timestamp: options.date.toISOString(), level: options.logLevel, message: options.message, fiberId: options.fiber.id, annotations: options.fiber.getRef(References.CurrentLogAnnotations)}))
// Custom filtering loggerconst filteredLogger = Logger.make((options) => { if (options.logLevel === "Debug") { return // Skip debug messages } return `${options.logLevel}: ${options.message}`})
const program = Effect.log("Hello World").pipe(Effect.provide(Logger.layer([textLogger])))Signature
declare const make: <Message, Output>(log: (options: Options<Message>) => Output) => Logger<Message, Output>Since v2.0.0
tracerLogger
Section titled “tracerLogger”A Logger which includes log messages as tracer span events.
Details
This logger integrates logging with distributed tracing by recording all log messages as events on the current trace span, making them visible in tracing tools like OpenTelemetry, Jaeger, or Zipkin.
This logger is included in the default set of loggers for all Effect programs, so log messages automatically appear as span events unless you override the default loggers.
Example (Recording logs as trace span events)
import { Effect, Logger } from "effect"
// Tracer logger is included by default - logs automatically become span eventsconst defaultProgram = Effect.gen(function* () { yield* Effect.log("This automatically becomes a span event") yield* Effect.logInfo("Processing data")})
// Explicitly combine tracer logger with other loggersconst observabilityProgram = Effect.gen(function* () { yield* Effect.log("Operation started") yield* Effect.logInfo("Processing data") yield* Effect.logError("Error occurred")}).pipe(Effect.withLogSpan("data-processing"), Effect.provide(Logger.layer([Logger.tracerLogger, Logger.consoleJson])))
// Perfect for correlating logs with traces in distributed systemsconst distributedProgram = Effect.gen(function* () { yield* Effect.log("Step 1: Fetching user data") yield* Effect.sleep("100 millis") yield* Effect.log("Step 2: Processing payment") yield* Effect.sleep("200 millis") yield* Effect.log("Step 3: Sending confirmation")}).pipe( Effect.withLogSpan("payment-workflow"), Effect.annotateLogs("userId", "user-123"), Effect.provide(Logger.layer([Logger.tracerLogger])))Signature
declare const tracerLogger: Logger<unknown, void>Since v2.0.0
context
Section titled “context”Creates a Layer which will overwrite the current set of loggers with the
specified array of loggers.
Details
If the specified array of loggers should be merged with the current set
of loggers (instead of overwriting them), set mergeWithExisting to true.
Example (Providing logger layers)
import { Effect, Logger } from "effect"
// Single logger layerconst JsonLoggerLive = Logger.layer([Logger.consoleJson])
// Multiple loggers layerconst MultiLoggerLive = Logger.layer([Logger.consoleJson, Logger.consolePretty(), Logger.formatStructured])
// Merge with existing loggersconst AdditionalLoggerLive = Logger.layer([Logger.consoleJson], { mergeWithExisting: true })
// Using multiple logger formatsconst jsonLogger = Logger.consoleJsonconst prettyLogger = Logger.consolePretty()
const CustomLoggerLive = Logger.layer([jsonLogger, prettyLogger])
const program = Effect.log("Application started").pipe(Effect.provide(CustomLoggerLive))Signature
declare const layer: < const Loggers extends ReadonlyArray<Logger<unknown, unknown> | Effect.Effect<Logger<unknown, unknown>, any, any>>>( loggers: Loggers, options?: { readonly mergeWithExisting?: boolean | undefined } | undefined) => Layer.Layer< never, Loggers extends readonly [] ? never : Effect.Error<Loggers[number]>, Exclude<Loggers extends readonly [] ? never : Effect.Services<Loggers[number]>, Scope.Scope>>Since v4.0.0
toFile
Section titled “toFile”Creates a scoped logger that writes string logger output to a file.
Details
The returned effect requires FileSystem and Scope. The file logger batches
string output, writes each batch to the specified path, and flushes remaining
entries when the scope closes.
Example (Writing JSON logs to a file)
import { Effect, Layer, Logger } from "effect"import { NodeFileSystem, NodeRuntime } from "@effect/platform-node"
const fileLogger = Logger.formatJson.pipe(Logger.toFile("/tmp/log.txt"))const LoggerLive = Logger.layer([fileLogger]).pipe(Layer.provide(NodeFileSystem.layer))
Effect.log("a").pipe( Effect.andThen(Effect.log("b")), Effect.andThen(Effect.log("c")), Effect.provide(LoggerLive), NodeRuntime.runMain)Example (Writing logs to files)
import { Duration, Effect, Logger } from "effect"import { NodeFileSystem } from "@effect/platform-node"
// Basic file logging. The scope keeps the file open while logs are emitted// and flushes pending entries when it closes.const basicFileLogger = Effect.scoped( Effect.gen(function* () { const fileLogger = yield* Logger.formatJson.pipe(Logger.toFile("/tmp/app.log"))
yield* Effect.log("Application started").pipe(Effect.provide(Logger.layer([fileLogger]))) })).pipe(Effect.provide(NodeFileSystem.layer))
// File logger with custom batch windowconst batchedFileLogger = Effect.scoped( Effect.gen(function* () { const fileLogger = yield* Logger.formatLogFmt.pipe( Logger.toFile("/var/log/myapp.log", { flag: "a", batchWindow: Duration.seconds(5) }) )
yield* Effect.all([Effect.log("Event 1"), Effect.log("Event 2"), Effect.log("Event 3")]).pipe( Effect.provide(Logger.layer([fileLogger])) ) })).pipe(Effect.provide(NodeFileSystem.layer))
// Multiple loggers: console + fileconst multiLogger = Effect.scoped( Effect.gen(function* () { const fileLogger = yield* Logger.formatJson.pipe(Logger.toFile("/tmp/production.log"))
const loggerLive = Logger.layer([Logger.consolePretty(), fileLogger])
yield* Effect.log("Production event").pipe(Effect.provide(loggerLive)) })).pipe(Effect.provide(NodeFileSystem.layer))Signature
declare const toFile: (( path: string, options?: | { readonly flag?: FileSystem.OpenFlag | undefined readonly mode?: number | undefined readonly batchWindow?: Duration.Input | undefined } | undefined) => <Message>( self: Logger<Message, string>) => Effect.Effect<Logger<Message, void>, PlatformError, Scope.Scope | FileSystem.FileSystem>) & (<Message>( self: Logger<Message, string>, path: string, options?: | { readonly flag?: FileSystem.OpenFlag | undefined readonly mode?: number | undefined readonly batchWindow?: Duration.Input | undefined } | undefined ) => Effect.Effect<Logger<Message, void>, PlatformError, Scope.Scope | FileSystem.FileSystem>)Since v4.0.0
guards
Section titled “guards”isLogger
Section titled “isLogger”Returns true if the specified value is a Logger, otherwise returns false.
Example (Checking logger values)
import { Logger } from "effect"
const myLogger = Logger.make((options) => { console.log(options.message)})
console.log(Logger.isLogger(myLogger)) // trueconsole.log(Logger.isLogger("not a logger")) // falseconsole.log(Logger.isLogger({ log: () => {} })) // falseSignature
declare const isLogger: (u: unknown) => u is Logger<unknown, unknown>Since v4.0.0
logging
Section titled “logging”withConsoleError
Section titled “withConsoleError”Returns a new Logger that writes all output of the specified Logger to
the console using console.error.
When to use
Use when logger output should be routed to console.error, such as error logs that
should appear on stderr instead of stdout.
Example (Writing logger output with console.error)
import { Effect, Logger } from "effect"
// Create an error-specific formatterconst errorFormatter = Logger.make((options) => `ERROR [${options.date.toISOString()}]: ${options.message}`)
// Route to console.errorconst errorLogger = Logger.withConsoleError(errorFormatter)
const program = Effect.logError("Database connection failed").pipe(Effect.provide(Logger.layer([errorLogger])))Signature
declare const withConsoleError: <Message, Output>(self: Logger<Message, Output>) => Logger<Message, void>Since v2.0.0
withConsoleLog
Section titled “withConsoleLog”Returns a new Logger that writes all output of the specified Logger to
the console using console.log.
When to use
Use when a logger’s string or object output should be routed to console.log for
development or debugging.
Example (Writing logger output with console.log)
import { Effect, Logger } from "effect"
// Create a custom formatterconst customFormatter = Logger.make( (options) => `[${options.date.toISOString()}] ${options.logLevel}: ${options.message}`)
// Route to consoleconst consoleLogger = Logger.withConsoleLog(customFormatter)
const program = Effect.log("Hello World").pipe(Effect.provide(Logger.layer([consoleLogger])))Signature
declare const withConsoleLog: <Message, Output>(self: Logger<Message, Output>) => Logger<Message, void>Since v2.0.0
withLeveledConsole
Section titled “withLeveledConsole”Returns a new Logger that writes all output of the specified Logger to
the console.
Details
Will use the appropriate console method (i.e. console.log, console.error,
etc.) based upon the current LogLevel.
Debug uses console.debug, Info uses console.info, Trace uses
console.trace, Warn uses console.warn, Error and Fatal use
console.error, and all other levels use console.log.
Example (Writing logs with level-based console methods)
import { Effect, Logger } from "effect"
const formatter = Logger.make((options) => `[${options.logLevel}] ${options.message}`)
const leveledLogger = Logger.withLeveledConsole(formatter)
const program = Effect.gen(function* () { yield* Effect.logInfo("Info message") // -> console.info yield* Effect.logWarning("Warning") // -> console.warn yield* Effect.logError("Error occurred") // -> console.error yield* Effect.logDebug("Debug info") // -> console.debug}).pipe(Effect.provide(Logger.layer([leveledLogger])))Signature
declare const withLeveledConsole: <Message, Output>(self: Logger<Message, Output>) => Logger<Message, void>Since v3.8.0
mapping
Section titled “mapping”Transforms the output of a Logger using the provided function.
When to use
Use when an existing logger’s output should be transformed without recreating the logging logic.
Example (Transforming logger output)
import { Logger } from "effect"
// Create a logger that outputs objectsconst structuredLogger = Logger.make((options) => ({ level: options.logLevel, message: options.message, timestamp: options.date.toISOString()}))
// Transform the output to JSON stringsconst jsonStringLogger = Logger.map(structuredLogger, (output) => JSON.stringify(output))
// Transform to uppercase messagesconst uppercaseLogger = Logger.map(structuredLogger, (output) => ({ ...output, message: String(output.message).toUpperCase()}))Signature
declare const map: (<Output, Output2>( f: (output: Output) => Output2) => <Message>(self: Logger<Message, Output>) => Logger<Message, Output2>) & (<Message, Output, Output2>( self: Logger<Message, Output>, f: (output: Output) => Output2 ) => Logger<Message, Output2>)Since v2.0.0
models
Section titled “models”Logger (interface)
Section titled “Logger (interface)”A logger that transforms a runtime log event into an output value.
Details
The runtime calls log with the message, level, cause, fiber, and timestamp
for each log event. Use Logger.layer to install one or more loggers for an
effect.
Example (Creating custom loggers)
import { Effect, Logger } from "effect"
// Create a custom logger that accepts unknown messages and returns voidconst stringLogger = Logger.make<unknown, void>((options) => { console.log(`[${options.logLevel}] ${options.message}`)})
// Create a logger that accepts any message type and returns a formatted stringconst formattedLogger = Logger.make<unknown, string>( (options) => `${options.date.toISOString()} [${options.logLevel}] ${options.message}`)
// Use the logger in an Effect programconst program = Effect.log("Hello World").pipe(Effect.provide(Logger.layer([stringLogger])))Signature
export interface Logger<in Message, out Output> extends Pipeable { readonly [TypeId]: typeof TypeId log(options: Options<Message>): Output}Since v2.0.0
options
Section titled “options”Options (interface)
Section titled “Options (interface)”Information supplied to a Logger for a single log event.
Details
Includes the logged message, log level, cause, current fiber, and timestamp.
Example (Accessing logger options)
import { Effect, Logger } from "effect"
// Options interface provides all logging contextconst detailedLogger = Logger.make((options) => { const output = { message: options.message, level: options.logLevel, timestamp: options.date.toISOString(), fiberId: options.fiber.id, hasCause: options.cause !== undefined } console.log(JSON.stringify(output))})
const program = Effect.log("Processing request").pipe(Effect.provide(Logger.layer([detailedLogger])))Signature
export interface Options<out Message> { readonly message: Message readonly logLevel: LogLevel.LogLevel readonly cause: Cause.Cause<unknown> readonly fiber: Fiber.Fiber<unknown, unknown> readonly date: Date}Since v2.0.0
references
Section titled “references”CurrentLoggers
Section titled “CurrentLoggers”Context reference containing the active loggers for the current fiber.
Details
By default this set includes the default logger and the tracer logger.
Providing Logger.layer replaces or merges with this set depending on its
options.
Example (Accessing current loggers)
import { Effect, Logger } from "effect"
// Access current loggers from fiber contextconst program = Effect.gen(function* () { const currentLoggers = yield* Effect.service(Logger.CurrentLoggers) console.log(`Number of active loggers: ${currentLoggers.size}`)
// Add a custom logger to the set const customLogger = Logger.make((options) => { console.log(`Custom: ${options.message}`) })
yield* Effect.log("Hello from custom logger").pipe(Effect.provide(Logger.layer([customLogger])))})Signature
declare const CurrentLoggers: Context.Reference<ReadonlySet<Logger<unknown, any>>>Since v4.0.0
LogToStderr
Section titled “LogToStderr”Context reference that routes the built-in default logger and TTY pretty console logger to stderr.
When to use
Use to route built-in logger output to stderr while keeping stdout reserved for protocol messages or data output.
Details
The reference defaults to false. Providing true makes the affected
loggers call console.error instead of console.log.
See
defaultLoggerfor the runtime logger affected by this referenceconsolePrettyfor the TTY-mode pretty console logger affected by this referencewithConsoleErrorfor routing a specific formatter logger toconsole.error
Signature
declare const LogToStderr: Context.Reference<boolean>Since v4.0.0