Skip to content

Logging

Logging is an important aspect of software development, especially for debugging and monitoring the behavior of your applications. In this section, we’ll explore Effect’s logging utilities and see how they compare to traditional logging methods.

Effect’s logging utilities provide several benefits over conventional logging approaches:

  1. Dynamic Log Level Control: With Effect’s logging, you have the ability to change the log level dynamically. This means you can control which log messages get displayed based on their severity. For example, you can configure your application to log only warnings or errors, which can be extremely helpful in production environments to reduce noise.

  2. Custom Logging Output: Effect’s logging utilities allow you to change how logs are handled. You can direct log messages to various destinations, such as a service or a file, using a custom logger. This flexibility ensures that logs are stored and processed in a way that best suits your application’s requirements.

  3. Fine-Grained Logging: Effect enables fine-grained control over logging on a per-part basis of your program. You can set different log levels for different parts of your application, tailoring the level of detail to each specific component. This can be invaluable for debugging and troubleshooting, as you can focus on the information that matters most.

  4. Environment-Based Logging: Effect’s logging utilities can be combined with deployment environments to achieve granular logging strategies. For instance, during development, you might choose to log everything at a trace level and above for detailed debugging. In contrast, your production version could be configured to log only errors or critical issues, minimizing the impact on performance and noise in production logs.

  5. Additional Features: Effect’s logging utilities come with additional features such as the ability to measure time spans, alter log levels on a per-effect basis, and integrate spans for performance monitoring.

The Effect.log function allows you to log a message at the default INFO level.

Example (Logging a Simple Message)

1
import {
import Effect
Effect
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("Application started")
4
5
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
)
6
/*
7
Output:
8
timestamp=... level=INFO fiber=#0 message="Application started"
9
*/

The default logger in Effect adds several useful details to each log entry:

AnnotationDescription
timestampThe timestamp when the log message was generated.
levelThe log level at which the message is logged (e.g., INFO, ERROR).
fiberThe identifier of the fiber executing the program.
messageThe log message content, which can include multiple strings or values.
span(Optional) The duration of a span in milliseconds, providing insight into the timing of operations.

You can also log multiple messages at once.

Example (Logging Multiple Messages)

1
import {
import Effect
Effect
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message1", "message2", "message3")
4
5
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
)
6
/*
7
Output:
8
timestamp=... level=INFO fiber=#0 message=message1 message=message2 message=message3
9
*/

For added context, you can also include one or more Cause instances in your logs, which provide detailed error information under an additional cause annotation:

Example (Logging with Causes)

1
import {
import Effect
Effect
,
import Cause
Cause
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
(
4
"message1",
5
"message2",
6
import Cause
Cause
.
const die: (defect: unknown) => Cause.Cause<never>

Constructs a new `Die` cause from the specified `defect`.

die
("Oh no!"),
7
import Cause
Cause
.
const die: (defect: unknown) => Cause.Cause<never>

Constructs a new `Die` cause from the specified `defect`.

die
("Oh uh!")
8
)
9
10
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
)
11
/*
12
Output:
13
timestamp=... level=INFO fiber=#0 message=message1 message=message2 cause="Error: Oh no!
14
Error: Oh uh!"
15
*/

By default, DEBUG messages are not displayed. To enable DEBUG logs, you can adjust the logging configuration using Logger.withMinimumLogLevel, setting the minimum level to LogLevel.Debug.

Example (Enabling Debug Logs)

1
import {
import Effect
Effect
,
import Logger
Logger
,
import LogLevel
LogLevel
} from "effect"
2
3
const
const task1: Effect.Effect<void, never, never>
task1
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
4
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("2 seconds")
5
yield*
import Effect
Effect
.
const logDebug: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified messages at the DEBUG log level. DEBUG messages are not shown by default. To view DEBUG messages, adjust the logging settings using `Logger.withMinimumLogLevel` and set the log level to `LogLevel.Debug`.

logDebug
("task1 done") // Log a debug message
6
}).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Logger
Logger
.
const withMinimumLogLevel: (level: LogLevel.LogLevel) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

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

withMinimumLogLevel
(
import LogLevel
LogLevel
.
const Debug: LogLevel.LogLevel
Debug
)) // Enable DEBUG level
7
8
const
const task2: Effect.Effect<void, never, never>
task2
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
9
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("1 second")
10
yield*
import Effect
Effect
.
const logDebug: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified messages at the DEBUG log level. DEBUG messages are not shown by default. To view DEBUG messages, adjust the logging settings using `Logger.withMinimumLogLevel` and set the log level to `LogLevel.Debug`.

logDebug
("task2 done") // This message won't be logged
11
})
12
13
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
14
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("start")
15
yield*
const task1: Effect.Effect<void, never, never>
task1
16
yield*
const task2: Effect.Effect<void, never, never>
task2
17
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("done")
18
})
19
20
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
)
21
/*
22
Output:
23
timestamp=... level=INFO message=start
24
timestamp=... level=DEBUG message="task1 done" <-- 2 seconds later
25
timestamp=... level=INFO message=done <-- 1 second later
26
*/

The INFO log level is displayed by default. This level is typically used for general application events or progress updates.

Example (Logging at the Info Level)

1
import {
import Effect
Effect
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
4
yield*
import Effect
Effect
.
const logInfo: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified message or cause at the Info log level.

logInfo
("start")
5
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("2 seconds")
6
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("1 second")
7
yield*
import Effect
Effect
.
const logInfo: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified message or cause at the Info log level.

logInfo
("done")
8
})
9
10
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
)
11
/*
12
Output:
13
timestamp=... level=INFO message=start
14
timestamp=... level=INFO message=done <-- 3 seconds later
15
*/

The WARN log level is displayed by default. This level is intended for potential issues or warnings that do not immediately disrupt the flow of the program but should be monitored.

Example (Logging at the Warning Level)

1
import {
import Effect
Effect
,
import Either
Either
} from "effect"
2
3
const
const task: Effect.Effect<number, string, never>
task
=
import Effect
Effect
.
const fail: <string>(error: string) => Effect.Effect<never, string, never>
fail
("Oh uh!").
(method) Pipeable.pipe<Effect.Effect<never, string, never>, Effect.Effect<number, string, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<never, string, never>) => Effect.Effect<number, string, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const as: <number>(value: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<number, E, R> (+1 overload)

This function maps the success value of an `Effect` value to a specified constant value.

as
(2))
4
5
const
const program: Effect.Effect<number, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, number, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
6
const
const failureOrSuccess: Either.Either<number, string>
failureOrSuccess
= yield*
import Effect
Effect
.
const either: <number, string, never>(self: Effect.Effect<number, string, never>) => Effect.Effect<Either.Either<number, string>, never, never>

Returns an effect whose failure and success have been lifted into an `Either`. The resulting effect cannot fail, because the failure case has been exposed as part of the `Either` success case. This method is useful for recovering from effects that may fail. The error parameter of the returned `Effect` is `never`, since it is guaranteed the effect does not model failure.

either
(
const task: Effect.Effect<number, string, never>
task
)
7
if (
import Either
Either
.
const isLeft: <number, string>(self: Either.Either<number, string>) => self is Either.Left<string, number>

Determine if a `Either` is a `Left`.

isLeft
(
const failureOrSuccess: Either.Either<number, string>
failureOrSuccess
)) {
8
yield*
import Effect
Effect
.
const logWarning: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified message or cause at the Warning log level.

logWarning
(
const failureOrSuccess: Either.Left<string, number>
failureOrSuccess
.
(property) Left<string, number>.left: string
left
)
9
return 0
10
} else {
11
return
const failureOrSuccess: Either.Right<string, number>
failureOrSuccess
.
(property) Right<string, number>.right: number
right
12
}
13
})
14
15
import Effect
Effect
.
const runFork: <number, never>(effect: Effect.Effect<number, never, never>, options?: RunForkOptions) => RuntimeFiber<number, never>
runFork
(
const program: Effect.Effect<number, never, never>
program
)
16
/*
17
Output:
18
timestamp=... level=WARN fiber=#0 message="Oh uh!"
19
*/

The ERROR log level is displayed by default. These messages represent issues that need to be addressed.

Example (Logging at the Error Level)

1
import {
import Effect
Effect
,
import Either
Either
} from "effect"
2
3
const
const task: Effect.Effect<number, string, never>
task
=
import Effect
Effect
.
const fail: <string>(error: string) => Effect.Effect<never, string, never>
fail
("Oh uh!").
(method) Pipeable.pipe<Effect.Effect<never, string, never>, Effect.Effect<number, string, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<never, string, never>) => Effect.Effect<number, string, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const as: <number>(value: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<number, E, R> (+1 overload)

This function maps the success value of an `Effect` value to a specified constant value.

as
(2))
4
5
const
const program: Effect.Effect<number, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, number, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
6
const
const failureOrSuccess: Either.Either<number, string>
failureOrSuccess
= yield*
import Effect
Effect
.
const either: <number, string, never>(self: Effect.Effect<number, string, never>) => Effect.Effect<Either.Either<number, string>, never, never>

Returns an effect whose failure and success have been lifted into an `Either`. The resulting effect cannot fail, because the failure case has been exposed as part of the `Either` success case. This method is useful for recovering from effects that may fail. The error parameter of the returned `Effect` is `never`, since it is guaranteed the effect does not model failure.

either
(
const task: Effect.Effect<number, string, never>
task
)
7
if (
import Either
Either
.
const isLeft: <number, string>(self: Either.Either<number, string>) => self is Either.Left<string, number>

Determine if a `Either` is a `Left`.

isLeft
(
const failureOrSuccess: Either.Either<number, string>
failureOrSuccess
)) {
8
yield*
import Effect
Effect
.
const logError: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified message or cause at the Error log level.

logError
(
const failureOrSuccess: Either.Left<string, number>
failureOrSuccess
.
(property) Left<string, number>.left: string
left
)
9
return 0
10
} else {
11
return
const failureOrSuccess: Either.Right<string, number>
failureOrSuccess
.
(property) Right<string, number>.right: number
right
12
}
13
})
14
15
import Effect
Effect
.
const runFork: <number, never>(effect: Effect.Effect<number, never, never>, options?: RunForkOptions) => RuntimeFiber<number, never>
runFork
(
const program: Effect.Effect<number, never, never>
program
)
16
/*
17
Output:
18
timestamp=... level=ERROR fiber=#0 message="Oh uh!"
19
*/

The FATAL log level is displayed by default. This log level is typically reserved for unrecoverable errors.

Example (Logging at the Fatal Level)

1
import {
import Effect
Effect
,
import Either
Either
} from "effect"
2
3
const
const task: Effect.Effect<number, string, never>
task
=
import Effect
Effect
.
const fail: <string>(error: string) => Effect.Effect<never, string, never>
fail
("Oh uh!").
(method) Pipeable.pipe<Effect.Effect<never, string, never>, Effect.Effect<number, string, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<never, string, never>) => Effect.Effect<number, string, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const as: <number>(value: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<number, E, R> (+1 overload)

This function maps the success value of an `Effect` value to a specified constant value.

as
(2))
4
5
const
const program: Effect.Effect<number, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, number, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
6
const
const failureOrSuccess: Either.Either<number, string>
failureOrSuccess
= yield*
import Effect
Effect
.
const either: <number, string, never>(self: Effect.Effect<number, string, never>) => Effect.Effect<Either.Either<number, string>, never, never>

Returns an effect whose failure and success have been lifted into an `Either`. The resulting effect cannot fail, because the failure case has been exposed as part of the `Either` success case. This method is useful for recovering from effects that may fail. The error parameter of the returned `Effect` is `never`, since it is guaranteed the effect does not model failure.

either
(
const task: Effect.Effect<number, string, never>
task
)
7
if (
import Either
Either
.
const isLeft: <number, string>(self: Either.Either<number, string>) => self is Either.Left<string, number>

Determine if a `Either` is a `Left`.

isLeft
(
const failureOrSuccess: Either.Either<number, string>
failureOrSuccess
)) {
8
yield*
import Effect
Effect
.
const logFatal: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified message or cause at the Fatal log level.

logFatal
(
const failureOrSuccess: Either.Left<string, number>
failureOrSuccess
.
(property) Left<string, number>.left: string
left
)
9
return 0
10
} else {
11
return
const failureOrSuccess: Either.Right<string, number>
failureOrSuccess
.
(property) Right<string, number>.right: number
right
12
}
13
})
14
15
import Effect
Effect
.
const runFork: <number, never>(effect: Effect.Effect<number, never, never>, options?: RunForkOptions) => RuntimeFiber<number, never>
runFork
(
const program: Effect.Effect<number, never, never>
program
)
16
/*
17
Output:
18
timestamp=... level=FATAL fiber=#0 message="Oh uh!"
19
*/

You can enhance your log outputs by adding custom annotations using the Effect.annotateLogs function. This allows you to attach extra metadata to each log entry, making it easier to trace and add context to your logs.

Enhance your log outputs by incorporating custom annotations with the Effect.annotateLogs function. This function allows you to append additional metadata to each log entry of an effect, enhancing traceability and context.

You can apply a single annotation as a key/value pair to all log entries within an effect.

Example (Single Key/Value Annotation)

1
import {
import Effect
Effect
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
4
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message1")
5
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message2")
6
}).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
7
// Annotation as key/value pair
8
import Effect
Effect
.
const annotateLogs: (key: string, value: unknown) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+3 overloads)

Augments log outputs by appending custom annotations to log entries generated within an effect. This function provides a way to add more context and detail to log messages, making them more informative and easier to trace.

annotateLogs
("key", "value")
9
)
10
11
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
)
12
/*
13
Output:
14
timestamp=... level=INFO fiber=#0 message=message1 key=value
15
timestamp=... level=INFO fiber=#0 message=message2 key=value
16
*/

In this example, all logs generated within the program will include the annotation key=value.

You can also apply multiple annotations at once by passing an object with key/value pairs. Each key/value pair will be added to every log entry within the effect.

Example (Multiple Annotations)

1
import {
import Effect
Effect
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
4
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message1")
5
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message2")
6
}).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
7
// Add multiple annotations
8
import Effect
Effect
.
const annotateLogs: (values: Record<string, unknown>) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+3 overloads)

Augments log outputs by appending custom annotations to log entries generated within an effect. This function provides a way to add more context and detail to log messages, making them more informative and easier to trace.

annotateLogs
({
(property) key1: string
key1
: "value1",
(property) key2: string
key2
: "value2" })
9
)
10
11
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
)
12
/*
13
Output:
14
timestamp=... level=INFO fiber=#0 message=message1 key2=value2 key1=value1
15
timestamp=... level=INFO fiber=#0 message=message2 key2=value2 key1=value1
16
*/

In this case, each log will contain both key1=value1 and key2=value2.

If you want to limit the scope of your annotations so that they only apply to certain log entries, you can use Effect.annotateLogsScoped. This function confines the annotations to logs produced within a specific scope.

Example (Scoped Annotations)

1
import {
import Effect
Effect
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, Scope>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, Scope>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
4
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("no annotations") // No annotations
5
yield*
import Effect
Effect
.
const annotateLogsScoped: (values: Record<string, unknown>) => Effect.Effect<void, never, Scope> (+1 overload)

Applies log annotations with a limited scope, restricting their appearance to specific sections of your effect computations. Use `Effect.annotateLogsScoped` to add metadata to logs that only appear within a defined `Scope`, making it easier to manage context-specific logging.

annotateLogsScoped
({
(property) key: string
key
: "value" }) // Scoped annotation
6
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message1") // Annotation applied
7
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message2") // Annotation applied
8
}).
(method) Pipeable.pipe<Effect.Effect<void, never, Scope>, Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, Scope>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
9
import Effect
Effect
.
const scoped: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Scope>>

Scopes all resources used in this workflow to the lifetime of the workflow, ensuring that their finalizers are run as soon as this workflow completes execution, whether by success, failure, or interruption.

scoped
,
10
// Outside scope, no annotations
11
import Effect
Effect
.
const andThen: <Effect.Effect<void, never, never>>(f: Effect.Effect<void, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, E, R> (+3 overloads)

Executes a sequence of two actions, typically two `Effect`s, where the second action can depend on the result of the first action. The `that` action can take various forms: - a value - a function returning a value - a promise - a function returning a promise - an effect - a function returning an effect

andThen
(
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("no annotations again"))
12
)
13
14
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
)
15
/*
16
Output:
17
timestamp=... level=INFO fiber=#0 message="no annotations"
18
timestamp=... level=INFO fiber=#0 message=message1 key=value
19
timestamp=... level=INFO fiber=#0 message=message2 key=value
20
timestamp=... level=INFO fiber=#0 message="no annotations again"
21
*/

Effect provides built-in support for log spans, which allow you to measure and log the duration of specific tasks or sections of your code. This feature is helpful for tracking how long certain operations take, giving you better insights into the performance of your application.

Example (Measuring Task Duration with a Log Span)

1
import {
import Effect
Effect
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
4
// Simulate a delay to represent a task taking time
5
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("1 second")
6
// Log a message indicating the job is done
7
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("The job is finished!")
8
}).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
9
// Apply a log span labeled "myspan" to measure
10
// the duration of this operation
11
import Effect
Effect
.
const withLogSpan: (label: string) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Adds a log span to your effects, which tracks and logs the duration of operations or tasks. This is useful for performance monitoring and debugging time-sensitive processes.

withLogSpan
("myspan")
12
)
13
14
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
)
15
/*
16
Output:
17
timestamp=... level=INFO fiber=#0 message="The job is finished!" myspan=1011ms
18
*/

Sometimes, perhaps during test execution, you might want to disable default logging in your application. Effect provides several ways to turn off logging when needed. In this section, we’ll look at different methods to disable logging in the Effect framework.

Example (Using Logger.withMinimumLogLevel)

One convenient way to disable logging is by using the Logger.withMinimumLogLevel function. This allows you to set the minimum log level to None, effectively turning off all log output.

1
import {
import Effect
Effect
,
import Logger
Logger
,
import LogLevel
LogLevel
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
4
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("Executing task...")
5
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("100 millis")
6
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
("task done")
7
})
8
9
// Default behavior: logging enabled
10
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
)
11
/*
12
Output:
13
timestamp=... level=INFO fiber=#0 message="Executing task..."
14
task done
15
*/
16
17
// Disable logging by setting minimum log level to 'None'
18
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
.
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Logger
Logger
.
const withMinimumLogLevel: (level: LogLevel.LogLevel) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

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

withMinimumLogLevel
(
import LogLevel
LogLevel
.
const None: LogLevel.LogLevel
None
)))
19
/*
20
Output:
21
task done
22
*/

Example (Using a Layer)

Another approach to disable logging is by creating a layer that sets the minimum log level to LogLevel.None, effectively turning off all log output.

1
import {
import Effect
Effect
,
import Logger
Logger
,
import LogLevel
LogLevel
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
4
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("Executing task...")
5
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("100 millis")
6
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
("task done")
7
})
8
9
// Create a layer that disables logging
10
const
const layer: Layer<never, never, never>
layer
=
import Logger
Logger
.
const minimumLogLevel: (level: LogLevel.LogLevel) => Layer<never>

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

minimumLogLevel
(
import LogLevel
LogLevel
.
const None: LogLevel.LogLevel
None
)
11
12
// Apply the layer to disable logging
13
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
.
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <never, never, never>(layer: Layer<never, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, never>> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
const layer: Layer<never, never, never>
layer
)))
14
/*
15
Output:
16
task done
17
*/

Example (Using a Custom Runtime)

You can also disable logging by creating a custom runtime that includes the configuration to turn off logging:

1
import {
import Effect
Effect
,
import Logger
Logger
,
import LogLevel
LogLevel
,
import ManagedRuntime
ManagedRuntime
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
4
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("Executing task...")
5
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("100 millis")
6
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
("task done")
7
})
8
9
// Create a custom runtime that disables logging
10
const
const customRuntime: ManagedRuntime.ManagedRuntime<never, never>
customRuntime
=
import ManagedRuntime
ManagedRuntime
.
const make: <never, never>(layer: Layer<never, never, never>, memoMap?: MemoMap | undefined) => ManagedRuntime.ManagedRuntime<never, never>

Convert a Layer into an ManagedRuntime, that can be used to run Effect's using your services.

make
(
11
import Logger
Logger
.
const minimumLogLevel: (level: LogLevel.LogLevel) => Layer<never>

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

minimumLogLevel
(
import LogLevel
LogLevel
.
const None: LogLevel.LogLevel
None
)
12
)
13
14
// Run the program using the custom runtime
15
const customRuntime: ManagedRuntime.ManagedRuntime<never, never>
customRuntime
.
(property) ManagedRuntime<never, never>.runFork: <void, never>(self: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>

Executes the effect using the provided Scheduler or using the global Scheduler if not provided

runFork
(
const program: Effect.Effect<void, never, never>
program
)
16
/*
17
Output:
18
task done
19
*/

To dynamically load the log level from a configuration and apply it to your program, you can use the Logger.minimumLogLevel layer. This allows your application to adjust its logging behavior based on external configuration.

Example (Loading Log Level from Configuration)

1
import {
2
import Effect
Effect
,
3
import Config
Config
,
4
import Logger
Logger
,
5
import Layer
Layer
,
6
import ConfigProvider
ConfigProvider
,
7
import LogLevel
LogLevel
8
} from "effect"
9
10
// Simulate a program with logs
11
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
12
yield*
import Effect
Effect
.
const logError: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified message or cause at the Error log level.

logError
("ERROR!")
13
yield*
import Effect
Effect
.
const logWarning: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified message or cause at the Warning log level.

logWarning
("WARNING!")
14
yield*
import Effect
Effect
.
const logInfo: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified message or cause at the Info log level.

logInfo
("INFO!")
15
yield*
import Effect
Effect
.
const logDebug: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified messages at the DEBUG log level. DEBUG messages are not shown by default. To view DEBUG messages, adjust the logging settings using `Logger.withMinimumLogLevel` and set the log level to `LogLevel.Debug`.

logDebug
("DEBUG!")
16
})
17
18
// Load the log level from the configuration and apply it as a layer
19
const
const LogLevelLive: Layer.Layer<never, ConfigError, never>
LogLevelLive
=
import Config
Config
.
const logLevel: (name?: string) => Config.Config<LogLevel.LogLevel>

Constructs a config for a `LogLevel` value.

logLevel
("LOG_LEVEL").
(method) Pipeable.pipe<Config.Config<LogLevel.LogLevel>, Effect.Effect<Layer.Layer<never, never, never>, ConfigError, never>, Layer.Layer<never, ConfigError, never>>(this: Config.Config<...>, ab: (_: Config.Config<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Layer.Layer<...>): Layer.Layer<...> (+21 overloads)
pipe
(
20
import Effect
Effect
.
const andThen: <LogLevel.LogLevel, Layer.Layer<never, never, never>>(f: (a: LogLevel.LogLevel) => Layer.Layer<never, never, never>) => <E, R>(self: Effect.Effect<LogLevel.LogLevel, E, R>) => Effect.Effect<...> (+3 overloads)

Executes a sequence of two actions, typically two `Effect`s, where the second action can depend on the result of the first action. The `that` action can take various forms: - a value - a function returning a value - a promise - a function returning a promise - an effect - a function returning an effect

andThen
((
(parameter) level: LogLevel.LogLevel
level
) =>
21
// Set the minimum log level
22
import Logger
Logger
.
const minimumLogLevel: (level: LogLevel.LogLevel) => Layer.Layer<never>

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

minimumLogLevel
(
(parameter) level: LogLevel.LogLevel
level
)
23
),
24
import Layer
Layer
.
const unwrapEffect: <A, E1, R1, E, R>(self: Effect.Effect<Layer.Layer<A, E1, R1>, E, R>) => Layer.Layer<A, E | E1, R | R1>
unwrapEffect
// Convert the effect into a layer
25
)
26
27
// Provide the loaded log level to the program
28
const
const configured: Effect.Effect<void, ConfigError, never>
configured
=
import Effect
Effect
.
const provide: <void, never, never, never, ConfigError, never>(self: Effect.Effect<void, never, never>, layer: Layer.Layer<never, ConfigError, never>) => Effect.Effect<...> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
const program: Effect.Effect<void, never, never>
program
,
const LogLevelLive: Layer.Layer<never, ConfigError, never>
LogLevelLive
)
29
30
// Test the program using a mock configuration provider
31
const
const test: Effect.Effect<void, ConfigError, never>
test
=
import Effect
Effect
.
const provide: <void, ConfigError, never, never, never, never>(self: Effect.Effect<void, ConfigError, never>, layer: Layer.Layer<never, never, never>) => Effect.Effect<...> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
32
const configured: Effect.Effect<void, ConfigError, never>
configured
,
33
import Layer
Layer
.
const setConfigProvider: (configProvider: ConfigProvider.ConfigProvider) => Layer.Layer<never>

Sets the current `ConfigProvider`.

setConfigProvider
(
34
import ConfigProvider
ConfigProvider
.
const fromMap: (map: Map<string, string>, config?: Partial<ConfigProvider.ConfigProvider.FromMapConfig>) => ConfigProvider.ConfigProvider

Constructs a ConfigProvider using a map and the specified delimiter string, which determines how to split the keys in the map into path segments.

fromMap
(
35
new
var Map: MapConstructor new <string, "ALL" | "FATAL" | "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE" | "OFF">(iterable?: Iterable<readonly [string, "ALL" | "FATAL" | "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE" | "OFF"]> | null | undefined) => Map<...> (+3 overloads)
Map
([["LOG_LEVEL",
import LogLevel
LogLevel
.
const Warning: LogLevel.LogLevel
Warning
.
(property) label: "ALL" | "FATAL" | "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE" | "OFF"
label
]])
36
)
37
)
38
)
39
40
import Effect
Effect
.
const runFork: <void, ConfigError>(effect: Effect.Effect<void, ConfigError, never>, options?: RunForkOptions) => RuntimeFiber<...>
runFork
(
const test: Effect.Effect<void, ConfigError, never>
test
)
41
/*
42
Output:
43
... level=ERROR fiber=#0 message=ERROR!
44
... level=WARN fiber=#0 message=WARNING!
45
*/

In this section, you’ll learn how to define a custom logger and set it as the default logger in your application. Custom loggers give you control over how log messages are handled, such as routing them to external services, writing to files, or formatting logs in a specific way.

You can define your own logger using the Logger.make function. This function allows you to specify how log messages should be processed.

Example (Defining a Simple Custom Logger)

1
import {
import Logger
Logger
} from "effect"
2
3
// Custom logger that outputs log messages to the console
4
const
const logger: Logger.Logger<unknown, void>
logger
=
import Logger
Logger
.
const make: <unknown, void>(log: (options: Logger.Logger<in Message, out Output>.Options<unknown>) => void) => Logger.Logger<unknown, void>

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

make
(({
(parameter) logLevel: LogLevel
logLevel
,
(parameter) message: unknown
message
}) => {
5
module globalThis
globalThis
.
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(`[${
(parameter) logLevel: LogLevel
logLevel
.
(property) label: "ALL" | "FATAL" | "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE" | "OFF"
label
}] ${
(parameter) message: unknown
message
}`)
6
})

In this example, the custom logger logs messages to the console with the log level and message formatted as [LogLevel] Message.

Let’s assume you have the following tasks and a program where you log some messages:

1
import {
import Effect
Effect
,
import Logger
Logger
} from "effect"
2
4 collapsed lines
3
// Custom logger that outputs log messages to the console
4
const
const logger: Logger.Logger<unknown, void>
logger
=
import Logger
Logger
.
const make: <unknown, void>(log: (options: Logger.Logger<in Message, out Output>.Options<unknown>) => void) => Logger.Logger<unknown, void>

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

make
(({
(parameter) logLevel: LogLevel
logLevel
,
(parameter) message: unknown
message
}) => {
5
module globalThis
globalThis
.
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(`[${
(parameter) logLevel: LogLevel
logLevel
.
(property) label: "ALL" | "FATAL" | "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE" | "OFF"
label
}] ${
(parameter) message: unknown
message
}`)
6
})
7
8
const
const task1: Effect.Effect<void, never, never>
task1
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
9
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("2 seconds")
10
yield*
import Effect
Effect
.
const logDebug: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified messages at the DEBUG log level. DEBUG messages are not shown by default. To view DEBUG messages, adjust the logging settings using `Logger.withMinimumLogLevel` and set the log level to `LogLevel.Debug`.

logDebug
("task1 done")
11
})
12
13
const
const task2: Effect.Effect<void, never, never>
task2
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
14
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("1 second")
15
yield*
import Effect
Effect
.
const logDebug: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified messages at the DEBUG log level. DEBUG messages are not shown by default. To view DEBUG messages, adjust the logging settings using `Logger.withMinimumLogLevel` and set the log level to `LogLevel.Debug`.

logDebug
("task2 done")
16
})
17
18
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
19
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("start")
20
yield*
const task1: Effect.Effect<void, never, never>
task1
21
yield*
const task2: Effect.Effect<void, never, never>
task2
22
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("done")
23
})

To replace the default logger with your custom logger, you can use the Logger.replace function. After creating a layer that replaces the default logger, you provide it to your program using Effect.provide.

Example (Replacing the Default Logger with a Custom Logger)

1
import {
import Effect
Effect
,
import Logger
Logger
,
import LogLevel
LogLevel
} from "effect"
2
21 collapsed lines
3
// Custom logger that outputs log messages to the console
4
const
const logger: Logger.Logger<unknown, void>
logger
=
import Logger
Logger
.
const make: <unknown, void>(log: (options: Logger.Logger<in Message, out Output>.Options<unknown>) => void) => Logger.Logger<unknown, void>

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

make
(({
(parameter) logLevel: LogLevel.LogLevel
logLevel
,
(parameter) message: unknown
message
}) => {
5
module globalThis
globalThis
.
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(`[${
(parameter) logLevel: LogLevel.LogLevel
logLevel
.
(property) label: "ALL" | "FATAL" | "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE" | "OFF"
label
}] ${
(parameter) message: unknown
message
}`)
6
})
7
8
const
const task1: Effect.Effect<void, never, never>
task1
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
9
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("2 seconds")
10
yield*
import Effect
Effect
.
const logDebug: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified messages at the DEBUG log level. DEBUG messages are not shown by default. To view DEBUG messages, adjust the logging settings using `Logger.withMinimumLogLevel` and set the log level to `LogLevel.Debug`.

logDebug
("task1 done")
11
})
12
13
const
const task2: Effect.Effect<void, never, never>
task2
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
14
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("1 second")
15
yield*
import Effect
Effect
.
const logDebug: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs the specified messages at the DEBUG log level. DEBUG messages are not shown by default. To view DEBUG messages, adjust the logging settings using `Logger.withMinimumLogLevel` and set the log level to `LogLevel.Debug`.

logDebug
("task2 done")
16
})
17
18
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
19
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("start")
20
yield*
const task1: Effect.Effect<void, never, never>
task1
21
yield*
const task2: Effect.Effect<void, never, never>
task2
22
yield*
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("done")
23
})
24
25
// Replace the default logger with the custom logger
26
const
const layer: Layer<never, never, never>
layer
=
import Logger
Logger
.
const replace: <void, void>(self: Logger.Logger<unknown, void>, that: Logger.Logger<unknown, void>) => Layer<never> (+1 overload)
replace
(
import Logger
Logger
.
const defaultLogger: Logger.Logger<unknown, void>
defaultLogger
,
const logger: Logger.Logger<unknown, void>
logger
)
27
28
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
29
const program: Effect.Effect<void, never, never>
program
.
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
30
import Logger
Logger
.
const withMinimumLogLevel: (level: LogLevel.LogLevel) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

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

withMinimumLogLevel
(
import LogLevel
LogLevel
.
const Debug: LogLevel.LogLevel
Debug
),
31
import Effect
Effect
.
const provide: <never, never, never>(layer: Layer<never, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, never>> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
const layer: Layer<never, never, never>
layer
)
32
)
33
)

When you run the above program, the following log messages are printed to the console:

Terminal window
[INFO] start
[DEBUG] task1 done
[DEBUG] task2 done
[INFO] done

Effect provides several built-in loggers that you can use depending on your logging needs. These loggers offer different formats, each suited for different environments or purposes, such as development, production, or integration with external logging services.

The logFmt logger outputs logs in a human-readable key-value format. This format is often used in development and production for its simplicity and readability in the console.

1
import {
import Effect
Effect
,
import Logger
Logger
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message1", "message2").
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
4
import Effect
Effect
.
const annotateLogs: (values: Record<string, unknown>) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+3 overloads)

Augments log outputs by appending custom annotations to log entries generated within an effect. This function provides a way to add more context and detail to log messages, making them more informative and easier to trace.

annotateLogs
({
(property) key1: string
key1
: "value1",
(property) key2: string
key2
: "value2" }),
5
import Effect
Effect
.
const withLogSpan: (label: string) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Adds a log span to your effects, which tracks and logs the duration of operations or tasks. This is useful for performance monitoring and debugging time-sensitive processes.

withLogSpan
("myspan")
6
)
7
8
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
.
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <never, never, never>(layer: Layer<never, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, never>> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
import Logger
Logger
.
const logFmt: Layer<never, never, never>

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

logFmt
)))

Output:

Terminal window
timestamp=... level=INFO fiber=#0 message=message1 message=message2 myspan=0ms key2=value2 key1=value1

The pretty logger enhances log output by using color and indentation for better readability, making it particularly useful during development when visually scanning logs in the console.

1
import {
import Effect
Effect
,
import Logger
Logger
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message1", "message2").
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
4
import Effect
Effect
.
const annotateLogs: (values: Record<string, unknown>) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+3 overloads)

Augments log outputs by appending custom annotations to log entries generated within an effect. This function provides a way to add more context and detail to log messages, making them more informative and easier to trace.

annotateLogs
({
(property) key1: string
key1
: "value1",
(property) key2: string
key2
: "value2" }),
5
import Effect
Effect
.
const withLogSpan: (label: string) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Adds a log span to your effects, which tracks and logs the duration of operations or tasks. This is useful for performance monitoring and debugging time-sensitive processes.

withLogSpan
("myspan")
6
)
7
8
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
.
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <never, never, never>(layer: Layer<never, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, never>> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
import Logger
Logger
.
const pretty: Layer<never, never, never>

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.

pretty
)))

Output:

Terminal window
[<timestamp>] INFO (#0) myspan=1ms: message1
message2
key2: value2
key1: value1

The structured logger provides highly structured logs. This format is useful for situations that require detailed traceability of events, often in environments where logs are processed and analyzed by automated systems.

1
import {
import Effect
Effect
,
import Logger
Logger
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message1", "message2").
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
4
import Effect
Effect
.
const annotateLogs: (values: Record<string, unknown>) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+3 overloads)

Augments log outputs by appending custom annotations to log entries generated within an effect. This function provides a way to add more context and detail to log messages, making them more informative and easier to trace.

annotateLogs
({
(property) key1: string
key1
: "value1",
(property) key2: string
key2
: "value2" }),
5
import Effect
Effect
.
const withLogSpan: (label: string) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Adds a log span to your effects, which tracks and logs the duration of operations or tasks. This is useful for performance monitoring and debugging time-sensitive processes.

withLogSpan
("myspan")
6
)
7
8
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
.
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <never, never, never>(layer: Layer<never, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, never>> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
import Logger
Logger
.
const structured: Layer<never, never, never>

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

structured
)))

Output:

Terminal window
{
message: [ 'message1', 'message2' ],
logLevel: 'INFO',
timestamp: '...',
cause: undefined,
annotations: { key2: 'value2', key1: 'value1' },
spans: { myspan: 0 },
fiberId: '#0'
}

The json logger formats log entries as JSON objects, which is ideal for environments where logs are ingested by systems that process JSON.

1
import {
import Effect
Effect
,
import Logger
Logger
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("message1", "message2").
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
4
import Effect
Effect
.
const annotateLogs: (values: Record<string, unknown>) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+3 overloads)

Augments log outputs by appending custom annotations to log entries generated within an effect. This function provides a way to add more context and detail to log messages, making them more informative and easier to trace.

annotateLogs
({
(property) key1: string
key1
: "value1",
(property) key2: string
key2
: "value2" }),
5
import Effect
Effect
.
const withLogSpan: (label: string) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Adds a log span to your effects, which tracks and logs the duration of operations or tasks. This is useful for performance monitoring and debugging time-sensitive processes.

withLogSpan
("myspan")
6
)
7
8
import Effect
Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
runFork
(
const program: Effect.Effect<void, never, never>
program
.
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <never, never, never>(layer: Layer<never, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, never>> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
import Logger
Logger
.
const json: Layer<never, never, never>

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

json
)))

Output:

Terminal window
{"message":["message1","message2"],"logLevel":"INFO","timestamp":"...","annotations":{"key2":"value2","key1":"value1"},"spans":{"myspan":0},"fiberId":"#0"}