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:
-
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.
-
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.
-
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.
-
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.
-
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)
1import { import Effect
Effect } from "effect"2
3const 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
5import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<void, never, never>
program)6/*7Output:8timestamp=... level=INFO fiber=#0 message="Application started"9*/
The default logger in Effect adds several useful details to each log entry:
Annotation | Description |
---|---|
timestamp | The timestamp when the log message was generated. |
level | The log level at which the message is logged (e.g., INFO , ERROR ). |
fiber | The identifier of the fiber executing the program. |
message | The 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)
1import { import Effect
Effect } from "effect"2
3const 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
5import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<void, never, never>
program)6/*7Output:8timestamp=... level=INFO fiber=#0 message=message1 message=message2 message=message39*/
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)
1import { import Effect
Effect, import Cause
Cause } from "effect"2
3const 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
10import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<void, never, never>
program)11/*12Output:13timestamp=... level=INFO fiber=#0 message=message1 message=message2 cause="Error: Oh no!14Error: 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)
1import { import Effect
Effect, import Logger
Logger, import LogLevel
LogLevel } from "effect"2
3const 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 message6}).(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 level7
8const 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 logged11})12
13const 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>
task116 yield* const task2: Effect.Effect<void, never, never>
task217 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
20import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<void, never, never>
program)21/*22Output:23timestamp=... level=INFO message=start24timestamp=... level=DEBUG message="task1 done" <-- 2 seconds later25timestamp=... level=INFO message=done <-- 1 second later26*/
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)
1import { import Effect
Effect } from "effect"2
3const 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
10import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<void, never, never>
program)11/*12Output:13timestamp=... level=INFO message=start14timestamp=... level=INFO message=done <-- 3 seconds later15*/
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)
1import { import Effect
Effect, import Either
Either } from "effect"2
3const const task: Effect.Effect<number, string, never>
task = import Effect
Effect.const fail: <string>(error: string) => Effect.Effect<never, string, never>
Creates an `Effect` that represents a recoverable error.
This `Effect` does not succeed but instead fails with the provided error. The
failure can be of any type, and will propagate through the effect pipeline
unless handled.
Use this function when you want to explicitly signal an error in an `Effect`
computation. The failed effect can later be handled with functions like
{@link
catchAll
}
or
{@link
catchTag
}
.
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
5const 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 010 } else {11 return const failureOrSuccess: Either.Right<string, number>
failureOrSuccess.(property) Right<string, number>.right: number
right12 }13})14
15import Effect
Effect.const runFork: <number, never>(effect: Effect.Effect<number, never, never>, options?: RunForkOptions) => RuntimeFiber<number, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<number, never, never>
program)16/*17Output:18timestamp=... 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)
1import { import Effect
Effect, import Either
Either } from "effect"2
3const const task: Effect.Effect<number, string, never>
task = import Effect
Effect.const fail: <string>(error: string) => Effect.Effect<never, string, never>
Creates an `Effect` that represents a recoverable error.
This `Effect` does not succeed but instead fails with the provided error. The
failure can be of any type, and will propagate through the effect pipeline
unless handled.
Use this function when you want to explicitly signal an error in an `Effect`
computation. The failed effect can later be handled with functions like
{@link
catchAll
}
or
{@link
catchTag
}
.
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
5const 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 010 } else {11 return const failureOrSuccess: Either.Right<string, number>
failureOrSuccess.(property) Right<string, number>.right: number
right12 }13})14
15import Effect
Effect.const runFork: <number, never>(effect: Effect.Effect<number, never, never>, options?: RunForkOptions) => RuntimeFiber<number, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<number, never, never>
program)16/*17Output:18timestamp=... 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)
1import { import Effect
Effect, import Either
Either } from "effect"2
3const const task: Effect.Effect<number, string, never>
task = import Effect
Effect.const fail: <string>(error: string) => Effect.Effect<never, string, never>
Creates an `Effect` that represents a recoverable error.
This `Effect` does not succeed but instead fails with the provided error. The
failure can be of any type, and will propagate through the effect pipeline
unless handled.
Use this function when you want to explicitly signal an error in an `Effect`
computation. The failed effect can later be handled with functions like
{@link
catchAll
}
or
{@link
catchTag
}
.
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
5const 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 010 } else {11 return const failureOrSuccess: Either.Right<string, number>
failureOrSuccess.(property) Right<string, number>.right: number
right12 }13})14
15import Effect
Effect.const runFork: <number, never>(effect: Effect.Effect<number, never, never>, options?: RunForkOptions) => RuntimeFiber<number, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<number, never, never>
program)16/*17Output:18timestamp=... 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)
1import { import Effect
Effect } from "effect"2
3const 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 pair8 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
11import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<void, never, never>
program)12/*13Output:14timestamp=... level=INFO fiber=#0 message=message1 key=value15timestamp=... level=INFO fiber=#0 message=message2 key=value16*/
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)
1import { import Effect
Effect } from "effect"2
3const 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 annotations8 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
11import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<void, never, never>
program)12/*13Output:14timestamp=... level=INFO fiber=#0 message=message1 key2=value2 key1=value115timestamp=... level=INFO fiber=#0 message=message2 key2=value2 key1=value116*/
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)
1import { import Effect
Effect } from "effect"2
3const 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 annotations5 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 annotation6 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 applied7 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 applied8}).(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 annotations11 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
14import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<void, never, never>
program)15/*16Output:17timestamp=... level=INFO fiber=#0 message="no annotations"18timestamp=... level=INFO fiber=#0 message=message1 key=value19timestamp=... level=INFO fiber=#0 message=message2 key=value20timestamp=... 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)
1import { import Effect
Effect } from "effect"2
3const 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 time5 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 done7 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 measure10 // the duration of this operation11 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
14import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<void, never, never>
program)15/*16Output:17timestamp=... level=INFO fiber=#0 message="The job is finished!" myspan=1011ms18*/
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.
1import { import Effect
Effect, import Logger
Logger, import LogLevel
LogLevel } from "effect"2
3const 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 enabled10import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const program: Effect.Effect<void, never, never>
program)11/*12Output:13timestamp=... level=INFO fiber=#0 message="Executing task..."14task done15*/16
17// Disable logging by setting minimum log level to 'None'18import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
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/*20Output:21task done22*/
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.
1import { import Effect
Effect, import Logger
Logger, import LogLevel
LogLevel } from "effect"2
3const 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 logging10const 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 logging13import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
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/*15Output:16task done17*/
Example (Using a Custom Runtime)
You can also disable logging by creating a custom runtime that includes the configuration to turn off logging:
1import { import Effect
Effect, import Logger
Logger, import LogLevel
LogLevel, import ManagedRuntime
ManagedRuntime } from "effect"2
3const 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 logging10const 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 runtime15const 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/*17Output:18task done19*/
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)
1import {2 import Effect
Effect,3 import Config
Config,4 import Logger
Logger,5 import Layer
Layer,6 import ConfigProvider
ConfigProvider,7 import LogLevel
LogLevel8} from "effect"9
10// Simulate a program with logs11const 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 layer19const 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 level22 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 layer25)26
27// Provide the loaded log level to the program28const 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 provider31const 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
40import Effect
Effect.const runFork: <void, ConfigError>(effect: Effect.Effect<void, ConfigError, never>, options?: RunForkOptions) => RuntimeFiber<...>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
runFork(const test: Effect.Effect<void, ConfigError, never>
test)41/*42Output: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)
1import { import Logger
Logger } from "effect"2
3// Custom logger that outputs log messages to the console4const 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:
1import { import Effect
Effect, import Logger
Logger } from "effect"2
4 collapsed lines
3// Custom logger that outputs log messages to the console4const 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
8const 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
13const 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
18const 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>
task121 yield* const task2: Effect.Effect<void, never, never>
task222 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)
1import { import Effect
Effect, import Logger
Logger, import LogLevel
LogLevel } from "effect"2
21 collapsed lines
3// Custom logger that outputs log messages to the console4const 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
8const 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
13const 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
18const 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>
task121 yield* const task2: Effect.Effect<void, never, never>
task222 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 logger26const 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
28import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
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:
[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.
1import { import Effect
Effect, import Logger
Logger } from "effect"2
3const 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
8import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
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:
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.
1import { import Effect
Effect, import Logger
Logger } from "effect"2
3const 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
8import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
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:
[<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.
1import { import Effect
Effect, import Logger
Logger } from "effect"2
3const 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
8import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
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:
{ 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.
1import { import Effect
Effect, import Logger
Logger } from "effect"2
3const 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
8import Effect
Effect.const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>
Executes an effect and returns a `RuntimeFiber` that represents the running computation.
Use `runFork` when you want to start an effect without blocking the current execution flow.
It returns a fiber that you can observe, interrupt, or join as needed.
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:
{"message":["message1","message2"],"logLevel":"INFO","timestamp":"...","annotations":{"key2":"value2","key1":"value1"},"spans":{"myspan":0},"fiberId":"#0"}