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>)
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.function formatJson(
input: unknown,
options?: {
readonly space?: number | string | undefined
}
): string
Stringifies a value to JSON safely, silently dropping circular references.
When to use
Use when you need valid JSON output, unlike format, and the input may
contain circular references that should be silently omitted rather than
throwing a TypeError.
Details
Uses JSON.stringify internally with a replacer that tracks the current
object ancestry. Circular references are replaced with undefined, which
omits them from object output. Redactable values are automatically redacted
before serialization. Values not supported by JSON, such as BigInt,
Symbol, undefined, and functions, follow standard JSON.stringify
behavior. The space parameter controls indentation and defaults to 0.
Example (Formatting compact JSON)
import { Formatter } from "effect"
console.log(Formatter.formatJson({ name: "Alice", age: 30 }))
// {"name":"Alice","age":30}
Example (Handling circular references)
import { Formatter } from "effect"
const obj: any = { name: "test" }
obj.self = obj
console.log(Formatter.formatJson(obj))
// {"name":"test"}
Example (Pretty-printed JSON)
import { Formatter } from "effect"
console.log(Formatter.formatJson({ name: "Alice", age: 30 }, { space: 2 }))
// {
// "name": "Alice",
// "age": 30
// }
formatJson)