Skip to main content Link Search Menu Expand Document (external link)

Logger overview

Added in v2.0.0


Table of contents


console

withConsoleError

Signature

export declare const withConsoleError: <M, O>(self: Logger<M, O>) => Logger<M, void>

Added in v2.0.0

withConsoleLog

Signature

export declare const withConsoleLog: <M, O>(self: Logger<M, O>) => Logger<M, void>

Added in v2.0.0

constructors

defaultLogger

Signature

export declare const defaultLogger: Logger<unknown, void>

Added in v2.0.0

json

The json logger formats log entries as JSON objects, making them easy to integrate with logging systems that consume JSON data.

Signature

export declare const json: Layer.Layer<never, never, never>

Example

import { Effect, Logger } from "effect"

const program = Effect.log("message1", "message2").pipe(
  Effect.annotateLogs({ key1: "value1", key2: "value2" }),
  Effect.withLogSpan("myspan")
)

// Effect.runFork(program.pipe(Effect.provide(Logger.json)))
// {"message":["message1","message2"],"logLevel":"INFO","timestamp":"...","annotations":{"key2":"value2","key1":"value1"},"spans":{"myspan":0},"fiberId":"#0"}

Added in v2.0.0

jsonLogger

The jsonLogger logger formats log entries as JSON objects, making them easy to integrate with logging systems that consume JSON data.

Signature

export declare const jsonLogger: Logger<unknown, string>

Example

import { Effect, Logger } from "effect"

const program = Effect.log("message1", "message2").pipe(
  Effect.annotateLogs({ key1: "value1", key2: "value2" }),
  Effect.withLogSpan("myspan")
)

// Effect.runFork(program.pipe(Effect.provide(Logger.json)))
// {"message":["message1","message2"],"logLevel":"INFO","timestamp":"...","annotations":{"key2":"value2","key1":"value1"},"spans":{"myspan":0},"fiberId":"#0"}

Added in v2.0.0

logFmt

This logger outputs logs in a human-readable format that is easy to read during development or in a production console.

Signature

export declare const logFmt: Layer.Layer<never, never, never>

Example

import { Effect, Logger } from "effect"

const program = Effect.log("message1", "message2").pipe(
  Effect.annotateLogs({ key1: "value1", key2: "value2" }),
  Effect.withLogSpan("myspan")
)

// Effect.runFork(program.pipe(Effect.provide(Logger.logFmt)))
// timestamp=... level=INFO fiber=#0 message=message1 message=message2 myspan=0ms key2=value2 key1=value1

Added in v2.0.0

logfmtLogger

This logger outputs logs in a human-readable format that is easy to read during development or in a production console.

Signature

export declare const logfmtLogger: Logger<unknown, string>

Example

import { Effect, Logger } from "effect"

const program = Effect.log("message1", "message2").pipe(
  Effect.annotateLogs({ key1: "value1", key2: "value2" }),
  Effect.withLogSpan("myspan")
)

// Effect.runFork(program.pipe(Effect.provide(Logger.logFmt)))
// timestamp=... level=INFO fiber=#0 message=message1 message=message2 myspan=0ms key2=value2 key1=value1

Added in v2.0.0

make

Creates a custom logger that formats log messages according to the provided function.

Signature

export declare const make: <Message, Output>(
  log: (options: Logger.Options<Message>) => Output
) => Logger<Message, Output>

Example

import { Effect, Logger, LogLevel } from "effect"

const logger = Logger.make(({ logLevel, message }) => {
  globalThis.console.log(`[${logLevel.label}] ${message}`)
})

const task1 = Effect.logDebug("task1 done")
const task2 = Effect.logDebug("task2 done")

const program = Effect.gen(function* () {
  yield* Effect.log("start")
  yield* task1
  yield* task2
  yield* Effect.log("done")
}).pipe(Logger.withMinimumLogLevel(LogLevel.Debug), Effect.provide(Logger.replace(Logger.defaultLogger, logger)))

// Effect.runFork(program)
// [INFO] start
// [DEBUG] task1 done
// [DEBUG] task2 done
// [INFO] done

Added in v2.0.0

none

A logger that does nothing in response to logging events.

Signature

export declare const none: Logger<unknown, void>

Added in v2.0.0

pretty

The pretty logger utilizes the capabilities of the console API to generate visually engaging and color-enhanced log outputs. This feature is particularly useful for improving the readability of log messages during development and debugging processes.

Signature

export declare const pretty: Layer.Layer<never, never, never>

Example

import { Effect, Logger } from "effect"

const program = Effect.log("message1", "message2").pipe(
  Effect.annotateLogs({ key1: "value1", key2: "value2" }),
  Effect.withLogSpan("myspan")
)

// Effect.runFork(program.pipe(Effect.provide(Logger.pretty)))
//         green --v                      v-- bold and cyan
// [07:51:54.434] INFO (#0) myspan=1ms: message1
//   message2
//    v-- bold
//   key2: value2
//   key1: value1

Added in v3.5.0

prettyLogger

The pretty logger utilizes the capabilities of the console API to generate visually engaging and color-enhanced log outputs. This feature is particularly useful for improving the readability of log messages during development and debugging processes.

Signature

export declare const prettyLogger: (
  options?:
    | {
        readonly colors?: "auto" | boolean | undefined
        readonly stderr?: boolean | undefined
        readonly formatDate?: ((date: Date) => string) | undefined
        readonly mode?: "browser" | "tty" | "auto" | undefined
      }
    | undefined
) => Logger<unknown, void>

Example

import { Effect, Logger } from "effect"

const program = Effect.log("message1", "message2").pipe(
  Effect.annotateLogs({ key1: "value1", key2: "value2" }),
  Effect.withLogSpan("myspan")
)

// Effect.runFork(program.pipe(Effect.provide(Logger.pretty)))
//         green --v                      v-- bold and cyan
// [07:51:54.434] INFO (#0) myspan=1ms: message1
//   message2
//    v-- bold
//   key2: value2
//   key1: value1

Added in v3.5.0

simple

Signature

export declare const simple: <A, B>(log: (a: A) => B) => Logger<A, B>

Added in v2.0.0

stringLogger

Signature

export declare const stringLogger: Logger<unknown, string>

Added in v2.0.0

structured

The structured logger provides detailed log outputs, structured in a way that retains comprehensive traceability of the events, suitable for deeper analysis and troubleshooting.

Signature

export declare const structured: Layer.Layer<never, never, never>

Example

import { Effect, Logger } from "effect"

const program = Effect.log("message1", "message2").pipe(
  Effect.annotateLogs({ key1: "value1", key2: "value2" }),
  Effect.withLogSpan("myspan")
)

// Effect.runFork(program.pipe(Effect.provide(Logger.structured)))
// {
//   message: [ 'message1', 'message2' ],
//   logLevel: 'INFO',
//   timestamp: '2024-07-09T14:05:41.623Z',
//   cause: undefined,
//   annotations: { key2: 'value2', key1: 'value1' },
//   spans: { myspan: 0 },
//   fiberId: '#0'
// }

Added in v2.0.0

structuredLogger

The structured logger provides detailed log outputs, structured in a way that retains comprehensive traceability of the events, suitable for deeper analysis and troubleshooting.

Signature

export declare const structuredLogger: Logger<
  unknown,
  {
    readonly logLevel: string
    readonly fiberId: string
    readonly timestamp: string
    readonly message: unknown
    readonly cause: string | undefined
    readonly annotations: Record<string, unknown>
    readonly spans: Record<string, number>
  }
>

Example

import { Effect, Logger } from "effect"

const program = Effect.log("message1", "message2").pipe(
  Effect.annotateLogs({ key1: "value1", key2: "value2" }),
  Effect.withLogSpan("myspan")
)

// Effect.runFork(program.pipe(Effect.provide(Logger.structured)))
// {
//   message: [ 'message1', 'message2' ],
//   logLevel: 'INFO',
//   timestamp: '2024-07-09T14:05:41.623Z',
//   cause: undefined,
//   annotations: { key2: 'value2', key1: 'value1' },
//   spans: { myspan: 0 },
//   fiberId: '#0'
// }

Added in v2.0.0

succeed

Signature

export declare const succeed: <A>(value: A) => Logger<unknown, A>

Added in v2.0.0

sync

Signature

export declare const sync: <A>(evaluate: LazyArg<A>) => Logger<unknown, A>

Added in v2.0.0

test

Signature

export declare const test: {
  <Message>(input: Message): <Output>(self: Logger<Message, Output>) => Output
  <Message, Output>(self: Logger<Message, Output>, input: Message): Output
}

Added in v2.0.0

tracerLogger

Signature

export declare const tracerLogger: Logger<unknown, void>

Added in v2.0.0

context

add

Signature

export declare const add: <B>(logger: Logger<unknown, B>) => Layer.Layer<never>

Added in v2.0.0

addEffect

Signature

export declare const addEffect: <A, E, R>(effect: Effect<Logger<unknown, A>, E, R>) => Layer.Layer<never, E, R>

Added in v2.0.0

addScoped

Signature

export declare const addScoped: <A, E, R>(
  effect: Effect<Logger<unknown, A>, E, R>
) => Layer.Layer<never, E, Exclude<R, Scope>>

Added in v2.0.0

minimumLogLevel

Sets the minimum log level for logging operations, allowing control over which log messages are displayed based on their severity.

Signature

export declare const minimumLogLevel: (level: LogLevel.LogLevel) => Layer.Layer<never>

Example

import { Effect, Logger, LogLevel } from "effect"

const program = Effect.gen(function* () {
  yield* Effect.log("Executing task...")
  yield* Effect.sleep("100 millis")
  console.log("task done")
})

// Logging disabled using a layer
// Effect.runFork(program.pipe(Effect.provide(Logger.minimumLogLevel(LogLevel.None))))
// task done

Added in v2.0.0

remove

Signature

export declare const remove: <A>(logger: Logger<unknown, A>) => Layer.Layer<never>

Added in v2.0.0

replace

Signature

export declare const replace: {
  <B>(that: Logger<unknown, B>): <A>(self: Logger<unknown, A>) => Layer.Layer<never>
  <A, B>(self: Logger<unknown, A>, that: Logger<unknown, B>): Layer.Layer<never>
}

Added in v2.0.0

replaceEffect

Signature

export declare const replaceEffect: {
  <B, E, R>(that: Effect<Logger<unknown, B>, E, R>): <A>(self: Logger<unknown, A>) => Layer.Layer<never, E, R>
  <A, B, E, R>(self: Logger<unknown, A>, that: Effect<Logger<unknown, B>, E, R>): Layer.Layer<never, E, R>
}

Added in v2.0.0

replaceScoped

Signature

export declare const replaceScoped: {
  <B, E, R>(
    that: Effect<Logger<unknown, B>, E, R>
  ): <A>(self: Logger<unknown, A>) => Layer.Layer<never, E, Exclude<R, Scope>>
  <A, B, E, R>(
    self: Logger<unknown, A>,
    that: Effect<Logger<unknown, B>, E, R>
  ): Layer.Layer<never, E, Exclude<R, Scope>>
}

Added in v2.0.0

withMinimumLogLevel

Sets the minimum log level for subsequent logging operations, allowing control over which log messages are displayed based on their severity.

Signature

export declare const withMinimumLogLevel: {
  (level: LogLevel.LogLevel): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
  <A, E, R>(self: Effect<A, E, R>, level: LogLevel.LogLevel): Effect<A, E, R>
}

Example

import { Effect, Logger, LogLevel } from "effect"

const program = Effect.logDebug("message1").pipe(Logger.withMinimumLogLevel(LogLevel.Debug))

// Effect.runFork(program)
// timestamp=... level=DEBUG fiber=#0 message=message1

Added in v2.0.0

filtering

filterLogLevel

Returns a version of this logger that only logs messages when the log level satisfies the specified predicate.

Signature

export declare const filterLogLevel: {
  (
    f: (logLevel: LogLevel.LogLevel) => boolean
  ): <Message, Output>(self: Logger<Message, Output>) => Logger<Message, Option.Option<Output>>
  <Message, Output>(
    self: Logger<Message, Output>,
    f: (logLevel: LogLevel.LogLevel) => boolean
  ): Logger<Message, Option.Option<Output>>
}

Added in v2.0.0

guards

isLogger

Returns true if the specified value is a Logger, otherwise returns false.

Signature

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

Added in v1.0.0

mapping

batched

Creates a batched logger that groups log messages together and processes them in intervals.

Signature

export declare const batched: {
  <Output, R>(
    window: DurationInput,
    f: (messages: Types.NoInfer<Output>[]) => Effect<void, never, R>
  ): <Message>(self: Logger<Message, Output>) => Effect<Logger<Message, void>, never, Scope | R>
  <Message, Output, R>(
    self: Logger<Message, Output>,
    window: DurationInput,
    f: (messages: Types.NoInfer<Output>[]) => Effect<void, never, R>
  ): Effect<Logger<Message, void>, never, Scope | R>
}

Example

import { Console, Effect, Logger } from "effect"

const LoggerLive = Logger.replaceScoped(
  Logger.defaultLogger,
  Logger.logfmtLogger.pipe(
    Logger.batched("500 millis", (messages) => Console.log("BATCH", `[\n${messages.join("\n")}\n]`))
  )
)

const program = Effect.gen(function* () {
  yield* Effect.log("one")
  yield* Effect.log("two")
  yield* Effect.log("three")
}).pipe(Effect.provide(LoggerLive))

// Effect.runFork(program)
// BATCH [
// timestamp=... level=INFO fiber=#0 message=one
// timestamp=... level=INFO fiber=#0 message=two
// timestamp=... level=INFO fiber=#0 message=three
// ]

Added in v2.0.0

map

Signature

export 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>
}

Added in v2.0.0

mapInput

Signature

export declare const mapInput: {
  <Message, Message2>(
    f: (message: Message2) => Message
  ): <Output>(self: Logger<Message, Output>) => Logger<Message2, Output>
  <Output, Message, Message2>(
    self: Logger<Message, Output>,
    f: (message: Message2) => Message
  ): Logger<Message2, Output>
}

Added in v2.0.0

mapInputOptions

Signature

export declare const mapInputOptions: {
  <Message, Message2>(
    f: (options: Logger.Options<Message2>) => Logger.Options<Message>
  ): <Output>(self: Logger<Message, Output>) => Logger<Message2, Output>
  <Output, Message, Message2>(
    self: Logger<Message, Output>,
    f: (options: Logger.Options<Message2>) => Logger.Options<Message>
  ): Logger<Message2, Output>
}

Added in v2.0.0

models

Logger (interface)

Signature

export interface Logger<in Message, out Output> extends Logger.Variance<Message, Output>, Pipeable {
  log(options: Logger.Options<Message>): Output
}

Added in v2.0.0

symbols

LoggerTypeId

Signature

export declare const LoggerTypeId: typeof LoggerTypeId

Added in v2.0.0

LoggerTypeId (type alias)

Signature

export type LoggerTypeId = typeof LoggerTypeId

Added in v2.0.0

tracing

withSpanAnnotations

Signature

export declare const withSpanAnnotations: <Message, Output>(self: Logger<Message, Output>) => Logger<Message, Output>

Added in v2.0.0

utils

Logger (namespace)

Added in v2.0.0

Options (interface)

Signature

export interface Options<out Message> {
  readonly fiberId: FiberId.FiberId
  readonly logLevel: LogLevel.LogLevel
  readonly message: Message
  readonly cause: Cause.Cause<unknown>
  readonly context: FiberRefs.FiberRefs
  readonly spans: List.List<LogSpan.LogSpan>
  readonly annotations: HashMap.HashMap<string, unknown>
  readonly date: Date
}

Added in v2.0.0

Variance (interface)

Signature

export interface Variance<in Message, out Output> {
  readonly [LoggerTypeId]: {
    readonly _Message: Types.Contravariant<Message>
    readonly _Output: Types.Covariant<Output>
  }
}

Added in v2.0.0

zipping

zip

Combines this logger with the specified logger to produce a new logger that logs to both this logger and that logger.

Signature

export declare const zip: {
  <Message2, Output2>(
    that: Logger<Message2, Output2>
  ): <Message, Output>(self: Logger<Message, Output>) => Logger<Message & Message2, [Output, Output2]>
  <Message, Output, Message2, Output2>(
    self: Logger<Message, Output>,
    that: Logger<Message2, Output2>
  ): Logger<Message & Message2, [Output, Output2]>
}

Added in v2.0.0

zipLeft

Signature

export declare const zipLeft: {
  <Message2, Output2>(
    that: Logger<Message2, Output2>
  ): <Message, Output>(self: Logger<Message, Output>) => Logger<Message & Message2, Output>
  <Message, Output, Message2, Output2>(
    self: Logger<Message, Output>,
    that: Logger<Message2, Output2>
  ): Logger<Message & Message2, Output>
}

Added in v2.0.0

zipRight

Signature

export declare const zipRight: {
  <Message2, Output2>(
    that: Logger<Message2, Output2>
  ): <Message, Output>(self: Logger<Message, Output>) => Logger<Message & Message2, Output2>
  <Message, Output, Message2, Output2>(
    self: Logger<Message, Output>,
    that: Logger<Message2, Output2>
  ): Logger<Message & Message2, Output2>
}

Added in v2.0.0