Skip to content

Logger.ts

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



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 seconds
const 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 example
const 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>)

Source

Since v2.0.0

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 logger
const jsonProgram = Effect.log("Hello JSON Console").pipe(Effect.provide(Logger.layer([Logger.consoleJson])))
// Perfect for production logging and log aggregation
const 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 services
const 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>

Source

Since v4.0.0

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 logger
const logfmtProgram = Effect.log("Hello LogFmt Console").pipe(Effect.provide(Logger.layer([Logger.consoleLogFmt])))
// Great for production environments
const 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 loggers
const multiLoggerLive = Logger.layer([Logger.consoleLogFmt, Logger.consolePretty()])

Signature

declare const consoleLogFmt: Logger<unknown, void>

Source

Since v4.0.0

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 settings
const basicPretty = Effect.log("Hello Pretty Format").pipe(Effect.provide(Logger.layer([Logger.consolePretty()])))
// Configure pretty logger options
const customPretty = Logger.consolePretty({
colors: true,
stderr: false,
mode: "tty",
formatDate: (date) => date.toLocaleTimeString()
})
// Perfect for development environment
const 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 environments
const 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>

Source

Since v4.0.0

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 logger
const structuredProgram = Effect.log("Hello Structured Console").pipe(
Effect.provide(Logger.layer([Logger.consoleStructured]))
)
// Perfect for development debugging
const 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 structure
const 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>

Source

Since v4.0.0

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 logger
const withDefaultLogger = Effect.log("Explicit default").pipe(Effect.provide(Logger.layer([Logger.defaultLogger])))
// Compare with custom logger
const customLogger = Logger.make((options) => {
console.log(`CUSTOM: ${options.message}`)
})

Signature

declare const defaultLogger: Logger<unknown, void>

Source

Since v2.0.0

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 logger
const jsonLoggerProgram = Effect.log("Hello JSON Format").pipe(Effect.provide(Logger.layer([Logger.formatJson])))
// Perfect for log aggregation and processing systems
const 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 sink
const envelopedJsonLogger = Logger.map(
Logger.formatJson,
(jsonString) => `{"service":"api-server","entry":${jsonString}}`
)
const envelopedConsoleLogger = Logger.withConsoleLog(envelopedJsonLogger)

Signature

declare const formatJson: Logger<unknown, string>

Source

Since v4.0.0

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 logger
const logfmtLoggerProgram = Effect.log("Hello LogFmt Format").pipe(Effect.provide(Logger.layer([Logger.formatLogFmt])))
// Perfect for structured logging systems
const 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, ELK
const productionLogger = Logger.formatLogFmt

Signature

declare const formatLogFmt: Logger<unknown, string>

Source

Since v4.0.0

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 logger
const simpleLoggerProgram = Effect.log("Hello Simple Format").pipe(Effect.provide(Logger.layer([Logger.formatSimple])))
// Combine with console output
const 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>

Source

Since v4.0.0

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 logger
const structuredLoggerProgram = Effect.log("Hello Structured Format").pipe(
Effect.provide(Logger.layer([Logger.formatStructured]))
)
// Perfect for JSON processing and analytics
const 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 output
const 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>
}
>

Source

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 logger
const textLogger = Logger.make((options) => `${options.date.toISOString()} [${options.logLevel}] ${options.message}`)
// Structured object logger
const 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 logger
const 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>

Source

Since v2.0.0

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 events
const defaultProgram = Effect.gen(function* () {
yield* Effect.log("This automatically becomes a span event")
yield* Effect.logInfo("Processing data")
})
// Explicitly combine tracer logger with other loggers
const 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 systems
const 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>

Source

Since v2.0.0

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 layer
const JsonLoggerLive = Logger.layer([Logger.consoleJson])
// Multiple loggers layer
const MultiLoggerLive = Logger.layer([Logger.consoleJson, Logger.consolePretty(), Logger.formatStructured])
// Merge with existing loggers
const AdditionalLoggerLive = Logger.layer([Logger.consoleJson], { mergeWithExisting: true })
// Using multiple logger formats
const jsonLogger = Logger.consoleJson
const 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>
>

Source

Since v4.0.0

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 window
const 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 + file
const 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>)

Source

Since v4.0.0

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)) // true
console.log(Logger.isLogger("not a logger")) // false
console.log(Logger.isLogger({ log: () => {} })) // false

Signature

declare const isLogger: (u: unknown) => u is Logger<unknown, unknown>

Source

Since v4.0.0

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 formatter
const errorFormatter = Logger.make((options) => `ERROR [${options.date.toISOString()}]: ${options.message}`)
// Route to console.error
const 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>

Source

Since v2.0.0

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 formatter
const customFormatter = Logger.make(
(options) => `[${options.date.toISOString()}] ${options.logLevel}: ${options.message}`
)
// Route to console
const 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>

Source

Since v2.0.0

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>

Source

Since v3.8.0

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 objects
const structuredLogger = Logger.make((options) => ({
level: options.logLevel,
message: options.message,
timestamp: options.date.toISOString()
}))
// Transform the output to JSON strings
const jsonStringLogger = Logger.map(structuredLogger, (output) => JSON.stringify(output))
// Transform to uppercase messages
const 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>)

Source

Since v2.0.0

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 void
const stringLogger = Logger.make<unknown, void>((options) => {
console.log(`[${options.logLevel}] ${options.message}`)
})
// Create a logger that accepts any message type and returns a formatted string
const formattedLogger = Logger.make<unknown, string>(
(options) => `${options.date.toISOString()} [${options.logLevel}] ${options.message}`
)
// Use the logger in an Effect program
const 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
}

Source

Since v2.0.0

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 context
const 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
}

Source

Since v2.0.0

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 context
const 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>>>

Source

Since v4.0.0

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

  • defaultLogger for the runtime logger affected by this reference
  • consolePretty for the TTY-mode pretty console logger affected by this reference
  • withConsoleError for routing a specific formatter logger to console.error

Signature

declare const LogToStderr: Context.Reference<boolean>

Source

Since v4.0.0