<Output>(options: {
readonly window: Duration.Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
}): <Message>(
self: Logger<Message, Output>
) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>
<Message, Output>(
self: Logger<Message, Output>,
options: {
readonly window: Duration.Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
}
): Effect.Effect<Logger<Message, void>, never, Scope.Scope>Creates a scoped logger that batches the output of another logger.
Details
The returned effect starts a scoped background process that periodically
passes buffered outputs to flush. When the scope closes, the background
process is interrupted and any remaining buffered entries are flushed.
Example (Batching logger output)
import { Duration, Effect, Logger } from "effect"
// Create a batched logger that flushes every 5 seconds
const batchedLogger = Logger.batched(Logger.formatJson, {
window: Duration.seconds(5),
flush: (messages) =>
Effect.sync(() => {
console.log(`Flushing ${messages.length} log entries:`)
messages.forEach((msg, i) => console.log(`${i + 1}. ${msg}`))
})
})
const program = Effect.gen(function*() {
const logger = yield* batchedLogger
yield* Effect.provide(
Effect.all([
Effect.log("Event 1"),
Effect.log("Event 2"),
Effect.log("Event 3"),
Effect.sleep(Duration.seconds(6)), // Trigger flush
Effect.log("Event 4")
]),
Logger.layer([logger])
)
})
// Remote batch logging example
const remoteBatchLogger = Logger.batched(Logger.formatStructured, {
window: Duration.seconds(10),
flush: (entries) =>
Effect.sync(() => {
// Send batch to remote logging service
console.log(`Sending ${entries.length} log entries to remote service`)
})
})export const const batched: (<Output>(options: {
readonly window: Duration.Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
}) => <Message>(
self: Logger<Message, Output>
) => Effect.Effect<
Logger<Message, void>,
never,
Scope.Scope
>) &
(<Message, Output>(
self: Logger<Message, Output>,
options: {
readonly window: Duration.Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
}
) => Effect.Effect<
Logger<Message, void>,
never,
Scope.Scope
>)
Creates a scoped logger that batches the output of another logger.
Details
The returned effect starts a scoped background process that periodically
passes buffered outputs to flush. When the scope closes, the background
process is interrupted and any remaining buffered entries are flushed.
Example (Batching logger output)
import { Duration, Effect, Logger } from "effect"
// Create a batched logger that flushes every 5 seconds
const batchedLogger = Logger.batched(Logger.formatJson, {
window: Duration.seconds(5),
flush: (messages) =>
Effect.sync(() => {
console.log(`Flushing ${messages.length} log entries:`)
messages.forEach((msg, i) => console.log(`${i + 1}. ${msg}`))
})
})
const program = Effect.gen(function*() {
const logger = yield* batchedLogger
yield* Effect.provide(
Effect.all([
Effect.log("Event 1"),
Effect.log("Event 2"),
Effect.log("Event 3"),
Effect.sleep(Duration.seconds(6)), // Trigger flush
Effect.log("Event 4")
]),
Logger.layer([logger])
)
})
// Remote batch logging example
const remoteBatchLogger = Logger.batched(Logger.formatStructured, {
window: Duration.seconds(10),
flush: (entries) =>
Effect.sync(() => {
// Send batch to remote logging service
console.log(`Sending ${entries.length} log entries to remote service`)
})
})
batched = dual<<Output>(options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}) => <Message>(self: Logger<Message, Output>) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>, <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>>(arity: 2, body: <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>): (<Output>(options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}) => <Message>(self: Logger<Message, Output>) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>) & (<Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>) (+1 overload)
Creates a function that can be called in data-first style or data-last
(pipe-friendly) style.
When to use
Use to expose one implementation through both direct and pipe-friendly
call styles.
Details
Pass either the arity of the uncurried function or a predicate that decides
whether the current call is data-first. Arity is the common case. Use a
predicate when optional arguments make arity ambiguous.
Example (Selecting data-first or data-last style by arity)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(2, (self, that) => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Defining overloads with call signatures)
import { Function, pipe } from "effect"
const sum: {
(that: number): (self: number) => number
(self: number, that: number): number
} = Function.dual(2, (self: number, that: number): number => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Selecting data-first or data-last style with a predicate)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(
(args) => args.length === 2,
(self, that) => self + that
)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
dual<
<function (type parameter) Output in <Output>(options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): <Message>(self: Logger<Message, Output>) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Output>(options: {
readonly window: Duration.Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
}
options: {
readonly window: Duration.Inputwindow: import DurationDuration.type Input =
| number
| bigint
| Duration.Duration
| readonly [seconds: number, nanos: number]
| `${number} nano`
| `${number} nanos`
| `${number} micro`
| `${number} micros`
| `${number} milli`
| `${number} millis`
| `${number} second`
| `${number} seconds`
| `${number} minute`
| `${number} minutes`
| `${number} hour`
| `${number} hours`
| `${number} day`
| `${number} days`
| `${number} week`
| `${number} weeks`
| "Infinity"
| "-Infinity"
| Duration.DurationObject
Valid input types that can be converted to a Duration.
When to use
Use when an API should accept any value that Effect can convert into a
Duration, including existing durations, millisecond numbers, nanosecond
bigints, high-resolution tuples, duration strings, infinity strings, or
duration objects.
Details
String inputs accept values like "10 seconds", "500 millis",
"Infinity", and "-Infinity". Finite fractional values that are
normalized to nanoseconds are rounded to the nearest nanosecond, with ties
away from zero.
Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
flush: (messages: NoInfer<Output>[]messages: interface Array<T>Array<type NoInfer<T> = intrinsicMarker for non-inference type position
NoInfer<function (type parameter) Output in <Output>(options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): <Message>(self: Logger<Message, Output>) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Output>>) => import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<void>
}) => <function (type parameter) Message in <Message>(self: Logger<Message, Output>): Effect.Effect<Logger<Message, void>, never, Scope.Scope>Message>(
self: Logger<Message, Output>(parameter) self: {
log: (options: Options<Message>) => Output;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self: interface Logger<in Message, out Output>A logger that transforms a runtime log event into an output value.
Details
The runtime calls log with the message, level, cause, fiber, and timestamp
for each log event. Use Logger.layer to install one or more loggers for an
effect.
Example (Creating custom loggers)
import { Effect, Logger } from "effect"
// Create a custom logger that accepts unknown messages and returns void
const stringLogger = Logger.make<unknown, void>((options) => {
console.log(`[${options.logLevel}] ${options.message}`)
})
// Create a logger that accepts any message type and returns a formatted string
const formattedLogger = Logger.make<unknown, string>((options) =>
`${options.date.toISOString()} [${options.logLevel}] ${options.message}`
)
// Use the logger in an Effect program
const program = Effect.log("Hello World").pipe(
Effect.provide(Logger.layer([stringLogger]))
)
Logger<function (type parameter) Message in <Message>(self: Logger<Message, Output>): Effect.Effect<Logger<Message, void>, never, Scope.Scope>Message, function (type parameter) Output in <Output>(options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): <Message>(self: Logger<Message, Output>) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Output>
) => import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<interface Logger<in Message, out Output>A logger that transforms a runtime log event into an output value.
Details
The runtime calls log with the message, level, cause, fiber, and timestamp
for each log event. Use Logger.layer to install one or more loggers for an
effect.
Example (Creating custom loggers)
import { Effect, Logger } from "effect"
// Create a custom logger that accepts unknown messages and returns void
const stringLogger = Logger.make<unknown, void>((options) => {
console.log(`[${options.logLevel}] ${options.message}`)
})
// Create a logger that accepts any message type and returns a formatted string
const formattedLogger = Logger.make<unknown, string>((options) =>
`${options.date.toISOString()} [${options.logLevel}] ${options.message}`
)
// Use the logger in an Effect program
const program = Effect.log("Hello World").pipe(
Effect.provide(Logger.layer([stringLogger]))
)
Logger<function (type parameter) Message in <Message>(self: Logger<Message, Output>): Effect.Effect<Logger<Message, void>, never, Scope.Scope>Message, void>, never, import ScopeScope.Scope>,
<function (type parameter) Message in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Message, function (type parameter) Output in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Output>(
self: Logger<Message, Output>(parameter) self: {
log: (options: Options<Message>) => Output;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self: interface Logger<in Message, out Output>A logger that transforms a runtime log event into an output value.
Details
The runtime calls log with the message, level, cause, fiber, and timestamp
for each log event. Use Logger.layer to install one or more loggers for an
effect.
Example (Creating custom loggers)
import { Effect, Logger } from "effect"
// Create a custom logger that accepts unknown messages and returns void
const stringLogger = Logger.make<unknown, void>((options) => {
console.log(`[${options.logLevel}] ${options.message}`)
})
// Create a logger that accepts any message type and returns a formatted string
const formattedLogger = Logger.make<unknown, string>((options) =>
`${options.date.toISOString()} [${options.logLevel}] ${options.message}`
)
// Use the logger in an Effect program
const program = Effect.log("Hello World").pipe(
Effect.provide(Logger.layer([stringLogger]))
)
Logger<function (type parameter) Message in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Message, function (type parameter) Output in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Output>,
options: {
readonly window: Duration.Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
}
options: {
readonly window: Duration.Inputwindow: import DurationDuration.type Input =
| number
| bigint
| Duration.Duration
| readonly [seconds: number, nanos: number]
| `${number} nano`
| `${number} nanos`
| `${number} micro`
| `${number} micros`
| `${number} milli`
| `${number} millis`
| `${number} second`
| `${number} seconds`
| `${number} minute`
| `${number} minutes`
| `${number} hour`
| `${number} hours`
| `${number} day`
| `${number} days`
| `${number} week`
| `${number} weeks`
| "Infinity"
| "-Infinity"
| Duration.DurationObject
Valid input types that can be converted to a Duration.
When to use
Use when an API should accept any value that Effect can convert into a
Duration, including existing durations, millisecond numbers, nanosecond
bigints, high-resolution tuples, duration strings, infinity strings, or
duration objects.
Details
String inputs accept values like "10 seconds", "500 millis",
"Infinity", and "-Infinity". Finite fractional values that are
normalized to nanoseconds are rounded to the nearest nanosecond, with ties
away from zero.
Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
flush: (messages: NoInfer<Output>[]messages: interface Array<T>Array<type NoInfer<T> = intrinsicMarker for non-inference type position
NoInfer<function (type parameter) Output in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Output>>) => import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<void>
}
) => import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<interface Logger<in Message, out Output>A logger that transforms a runtime log event into an output value.
Details
The runtime calls log with the message, level, cause, fiber, and timestamp
for each log event. Use Logger.layer to install one or more loggers for an
effect.
Example (Creating custom loggers)
import { Effect, Logger } from "effect"
// Create a custom logger that accepts unknown messages and returns void
const stringLogger = Logger.make<unknown, void>((options) => {
console.log(`[${options.logLevel}] ${options.message}`)
})
// Create a logger that accepts any message type and returns a formatted string
const formattedLogger = Logger.make<unknown, string>((options) =>
`${options.date.toISOString()} [${options.logLevel}] ${options.message}`
)
// Use the logger in an Effect program
const program = Effect.log("Hello World").pipe(
Effect.provide(Logger.layer([stringLogger]))
)
Logger<function (type parameter) Message in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Message, void>, never, import ScopeScope.Scope>
>(2, <function (type parameter) Message in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Message, function (type parameter) Output in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Output>(
self: Logger<Message, Output>(parameter) self: {
log: (options: Options<Message>) => Output;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self: interface Logger<in Message, out Output>A logger that transforms a runtime log event into an output value.
Details
The runtime calls log with the message, level, cause, fiber, and timestamp
for each log event. Use Logger.layer to install one or more loggers for an
effect.
Example (Creating custom loggers)
import { Effect, Logger } from "effect"
// Create a custom logger that accepts unknown messages and returns void
const stringLogger = Logger.make<unknown, void>((options) => {
console.log(`[${options.logLevel}] ${options.message}`)
})
// Create a logger that accepts any message type and returns a formatted string
const formattedLogger = Logger.make<unknown, string>((options) =>
`${options.date.toISOString()} [${options.logLevel}] ${options.message}`
)
// Use the logger in an Effect program
const program = Effect.log("Hello World").pipe(
Effect.provide(Logger.layer([stringLogger]))
)
Logger<function (type parameter) Message in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Message, function (type parameter) Output in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Output>,
options: {
readonly window: Duration.Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
}
options: {
readonly window: Duration.Inputwindow: import DurationDuration.type Input =
| number
| bigint
| Duration.Duration
| readonly [seconds: number, nanos: number]
| `${number} nano`
| `${number} nanos`
| `${number} micro`
| `${number} micros`
| `${number} milli`
| `${number} millis`
| `${number} second`
| `${number} seconds`
| `${number} minute`
| `${number} minutes`
| `${number} hour`
| `${number} hours`
| `${number} day`
| `${number} days`
| `${number} week`
| `${number} weeks`
| "Infinity"
| "-Infinity"
| Duration.DurationObject
Valid input types that can be converted to a Duration.
When to use
Use when an API should accept any value that Effect can convert into a
Duration, including existing durations, millisecond numbers, nanosecond
bigints, high-resolution tuples, duration strings, infinity strings, or
duration objects.
Details
String inputs accept values like "10 seconds", "500 millis",
"Infinity", and "-Infinity". Finite fractional values that are
normalized to nanoseconds are rounded to the nearest nanosecond, with ties
away from zero.
Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
flush: (messages: NoInfer<Output>[]messages: interface Array<T>Array<type NoInfer<T> = intrinsicMarker for non-inference type position
NoInfer<function (type parameter) Output in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Output>>) => import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<void>
}
): import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<interface Logger<in Message, out Output>A logger that transforms a runtime log event into an output value.
Details
The runtime calls log with the message, level, cause, fiber, and timestamp
for each log event. Use Logger.layer to install one or more loggers for an
effect.
Example (Creating custom loggers)
import { Effect, Logger } from "effect"
// Create a custom logger that accepts unknown messages and returns void
const stringLogger = Logger.make<unknown, void>((options) => {
console.log(`[${options.logLevel}] ${options.message}`)
})
// Create a logger that accepts any message type and returns a formatted string
const formattedLogger = Logger.make<unknown, string>((options) =>
`${options.date.toISOString()} [${options.logLevel}] ${options.message}`
)
// Use the logger in an Effect program
const program = Effect.log("Hello World").pipe(
Effect.provide(Logger.layer([stringLogger]))
)
Logger<function (type parameter) Message in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Message, void>, never, import ScopeScope.Scope> =>
import effecteffect.const flatMap: {
<A, B, E2, R2>(
f: (a: A) => Effect.Effect<B, E2, R2>
): <E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<B, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect.Effect<A, E, R>,
f: (a: A) => Effect.Effect<B, E2, R2>
): Effect.Effect<B, E | E2, R | R2>
}
flatMap(import effecteffect.const scope: Effect.Effect<
Scope.Scope,
never,
Scope.Scope
>
const scope: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
scope, (scope: Scope.Scope(parameter) scope: {
strategy: "sequential" | "parallel";
state: State.Open | State.Closed | State.Empty;
}
scope) => {
let let buffer: Output[]buffer: interface Array<T>Array<function (type parameter) Output in <Message, Output>(self: Logger<Message, Output>, options: {
readonly window: Duration.Input;
readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>;
}): Effect.Effect<Logger<Message, void>, never, Scope.Scope>
Output> = []
const const flush: Effect.Effect<
void,
never,
never
>
const flush: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
flush = import effecteffect.const suspend: <A, E, R>(
evaluate: LazyArg<Effect.Effect<A, E, R>>
) => Effect.Effect<A, E, R>
suspend(() => {
if (let buffer: Output[]buffer.globalThis.Array<T>.length: numberGets or sets the length of the array. This is a number one higher than the highest index in the array.
length === 0) {
return import effecteffect.const void: Effect.Effect<void, never, never>(alias) const void: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
void
}
const const arr: Output[]arr = let buffer: Output[]buffer
let buffer: Output[]buffer = []
return options: {
readonly window: Duration.Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
}
options.flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
flush(const arr: Output[]arr)
})
return import effecteffect.const uninterruptibleMask: <A, E, R>(
f: (
restore: <A, E, R>(
effect: Effect.Effect<A, E, R>
) => Effect.Effect<A, E, R>
) => Effect.Effect<A, E, R>
) => Effect.Effect<A, E, R>
uninterruptibleMask((restore: <A, E, R>(
effect: Effect.Effect<A, E, R>
) => Effect.Effect<A, E, R>
restore) =>
restore: <A, E, R>(
effect: Effect.Effect<A, E, R>
) => Effect.Effect<A, E, R>
restore(
import effecteffect.const sleep: (
duration: Duration.Input
) => Effect.Effect<void>
sleep(options: {
readonly window: Duration.Input
readonly flush: (
messages: Array<NoInfer<Output>>
) => Effect.Effect<void>
}
options.window: Duration.Inputwindow).Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Effect.Effect<never, never, never>>(this: Effect.Effect<void, never, never>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>, bc: (_: Effect.Effect<void, never, never>) => Effect.Effect<never, never, never>): Effect.Effect<never, never, never> (+21 overloads)pipe(
import effecteffect.const andThen: {
<A, B, E2, R2>(
f: (a: A) => Effect.Effect<B, E2, R2>
): <E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<B, E | E2, R | R2>
<B, E2, R2>(f: Effect.Effect<B, E2, R2>): <
A,
E,
R
>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<B, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect.Effect<A, E, R>,
f: (a: A) => Effect.Effect<B, E2, R2>
): Effect.Effect<B, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect.Effect<A, E, R>,
f: Effect.Effect<B, E2, R2>
): Effect.Effect<B, E | E2, R | R2>
}
andThen(const flush: Effect.Effect<
void,
never,
never
>
const flush: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
flush),
import effecteffect.const forever: {
<
Arg extends
| Effect.Effect<any, any, any>
| {
readonly disableYield?:
| boolean
| undefined
}
| undefined = {
readonly disableYield?: boolean | undefined
}
>(
effectOrOptions: Arg,
options?:
| {
readonly disableYield?:
| boolean
| undefined
}
| undefined
): [Arg] extends [
Effect.Effect<infer _A, infer _E, infer _R>
]
? Effect.Effect<never, _E, _R>
: <A, E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<never, E, R>
}
forever
)
).Pipeable.pipe<Effect.Effect<never, never, never>, Effect.Effect<Fiber.Fiber<never, never>, never, never>, Effect.Effect<void, never, never>, Effect.Effect<void, never, Scope.Scope>, Effect.Effect<Logger<Message, void>, never, Scope.Scope>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<never, never, never>) => Effect.Effect<Fiber.Fiber<never, never>, never, never>, bc: (_: Effect.Effect<Fiber.Fiber<never, never>, never, never>) => Effect.Effect<void, never, never>, cd: (_: Effect.Effect<...>) => Effect.Effect<...>, de: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)pipe(
import effecteffect.const forkDetach: {
<
Arg extends
| Effect.Effect<any, any, any>
| {
readonly startImmediately?:
| boolean
| undefined
readonly uninterruptible?:
| boolean
| "inherit"
| undefined
}
| undefined = {
readonly startImmediately?:
| boolean
| undefined
readonly uninterruptible?:
| boolean
| "inherit"
| undefined
}
>(
effectOrOptions: Arg,
options?:
| {
readonly startImmediately?:
| boolean
| undefined
readonly uninterruptible?:
| boolean
| "inherit"
| undefined
}
| undefined
): [Arg] extends [
Effect.Effect<infer _A, infer _E, infer _R>
]
? Effect.Effect<
Fiber.Fiber<_A, _E>,
never,
_R
>
: <A, E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<
Fiber.Fiber<A, E>,
never,
R
>
}
forkDetach,
import effecteffect.const flatMap: {
<A, B, E2, R2>(
f: (a: A) => Effect.Effect<B, E2, R2>
): <E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<B, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect.Effect<A, E, R>,
f: (a: A) => Effect.Effect<B, E2, R2>
): Effect.Effect<B, E | E2, R | R2>
}
flatMap((fiber: Fiber.Fiber<never, never>(parameter) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
fiber) => import effecteffect.const scopeAddFinalizerExit: (
scope: Scope.Scope,
finalizer: (
exit: Exit.Exit<any, any>
) => Effect.Effect<unknown>
) => Effect.Effect<void>
scopeAddFinalizerExit(scope: Scope.Scope(parameter) scope: {
strategy: "sequential" | "parallel";
state: State.Open | State.Closed | State.Empty;
}
scope, () => import effecteffect.const fiberInterrupt: <A, E>(
self: Fiber.Fiber<A, E>
) => Effect.Effect<void>
fiberInterrupt(fiber: Fiber.Fiber<never, never>(parameter) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
fiber))),
import effecteffect.const andThen: {
<A, B, E2, R2>(
f: (a: A) => Effect.Effect<B, E2, R2>
): <E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<B, E | E2, R | R2>
<B, E2, R2>(f: Effect.Effect<B, E2, R2>): <
A,
E,
R
>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<B, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect.Effect<A, E, R>,
f: (a: A) => Effect.Effect<B, E2, R2>
): Effect.Effect<B, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect.Effect<A, E, R>,
f: Effect.Effect<B, E2, R2>
): Effect.Effect<B, E | E2, R | R2>
}
andThen(import effecteffect.const addFinalizer: <R>(
finalizer: (
exit: Exit.Exit<unknown, unknown>
) => Effect.Effect<void, never, R>
) => Effect.Effect<void, never, R | Scope.Scope>
addFinalizer(() => const flush: Effect.Effect<
void,
never,
never
>
const flush: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
flush)),
import effecteffect.const as: {
<A, B>(value: B): <E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<B, E, R>
<A, E, R, B>(
self: Effect.Effect<A, E, R>,
value: B
): Effect.Effect<B, E, R>
}
as(
import effecteffect.const loggerMake: <Message, Output>(
log: (
options: Logger.Options<Message>
) => Output
) => Logger.Logger<Message, Output>
loggerMake((options: Options<Message>(parameter) options: {
message: Message;
logLevel: LogLevel.LogLevel;
cause: Cause.Cause<unknown>;
fiber: Fiber.Fiber<unknown, unknown>;
date: Date;
}
options) => {
let buffer: Output[]buffer.globalThis.Array<Output>.push(...items: Output[]): numberAppends new elements to the end of an array, and returns the new length of the array.
push(self: Logger<Message, Output>(parameter) self: {
log: (options: Options<Message>) => Output;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self.Logger<Message, Output>.log(options: Options<Message>): Outputlog(options: Options<Message>(parameter) options: {
message: Message;
logLevel: LogLevel.LogLevel;
cause: Cause.Cause<unknown>;
fiber: Fiber.Fiber<unknown, unknown>;
date: Date;
}
options))
})
)
)
)
}))