Logger<unknown, string>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)export const const formatJson: Logger<unknown, string>const formatJson: {
log: (options: Options<unknown>) => string;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
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)
formatJson = 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>)
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() })
)
map(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>
}
>
const formatStructured: {
log: (options: Options<unknown>) => { readonly level: string; readonly fiberId: string; readonly timestamp: string; readonly message: unknown; readonly cause: string | undefined; readonly annotations: Record<string, unknown>; readonly spans: Re…;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
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
})
formatStructured, import FormatterFormatter.formatJson)