<
const Loggers extends ReadonlyArray<
| Logger<unknown, unknown>
| Effect.Effect<Logger<unknown, unknown>, any, any>
>
>(
loggers: Loggers,
options?:
| { readonly mergeWithExisting?: boolean | undefined }
| undefined
): Layer.Layer<
never,
Loggers extends readonly [] ? never : Effect.Error<Loggers[number]>,
Exclude<
Loggers extends readonly []
? never
: Effect.Services<Loggers[number]>,
Scope.Scope
>
>Creates a Layer which will overwrite the current set of loggers with the
specified array of loggers.
Details
If the specified array of loggers should be merged with the current set
of loggers (instead of overwriting them), set mergeWithExisting to true.
Example (Providing logger layers)
import { Effect, Logger } from "effect"
// Single logger layer
const JsonLoggerLive = Logger.layer([Logger.consoleJson])
// Multiple loggers layer
const MultiLoggerLive = Logger.layer([
Logger.consoleJson,
Logger.consolePretty(),
Logger.formatStructured
])
// Merge with existing loggers
const AdditionalLoggerLive = Logger.layer(
[Logger.consoleJson],
{ mergeWithExisting: true }
)
// Using multiple logger formats
const jsonLogger = Logger.consoleJson
const prettyLogger = Logger.consolePretty()
const CustomLoggerLive = Logger.layer([jsonLogger, prettyLogger])
const program = Effect.log("Application started").pipe(
Effect.provide(CustomLoggerLive)
)export const const layer: <
Loggers extends ReadonlyArray<
| Logger<unknown, unknown>
| Effect.Effect<
Logger<unknown, unknown>,
any,
any
>
>
>(
loggers: Loggers,
options?:
| {
readonly mergeWithExisting?:
| boolean
| undefined
}
| undefined
) => Layer.Layer<
never,
Loggers extends readonly []
? never
: Effect.Error<Loggers[number]>,
Exclude<
Loggers extends readonly []
? never
: Effect.Services<Loggers[number]>,
Scope.Scope
>
>
Creates a Layer which will overwrite the current set of loggers with the
specified array of loggers.
Details
If the specified array of loggers should be merged with the current set
of loggers (instead of overwriting them), set mergeWithExisting to true.
Example (Providing logger layers)
import { Effect, Logger } from "effect"
// Single logger layer
const JsonLoggerLive = Logger.layer([Logger.consoleJson])
// Multiple loggers layer
const MultiLoggerLive = Logger.layer([
Logger.consoleJson,
Logger.consolePretty(),
Logger.formatStructured
])
// Merge with existing loggers
const AdditionalLoggerLive = Logger.layer(
[Logger.consoleJson],
{ mergeWithExisting: true }
)
// Using multiple logger formats
const jsonLogger = Logger.consoleJson
const prettyLogger = Logger.consolePretty()
const CustomLoggerLive = Logger.layer([jsonLogger, prettyLogger])
const program = Effect.log("Application started").pipe(
Effect.provide(CustomLoggerLive)
)
layer = <
const function (type parameter) Loggers in <const Loggers extends ReadonlyArray<Logger<unknown, unknown> | Effect.Effect<Logger<unknown, unknown>, any, any>>>(loggers: Loggers, options?: {
readonly mergeWithExisting?: boolean | undefined;
} | undefined): Layer.Layer<never, Loggers extends readonly [] ? never : Effect.Error<Loggers[number]>, Exclude<Loggers extends readonly [] ? never : Effect.Services<Loggers[number]>, Scope.Scope>>
Loggers extends interface ReadonlyArray<T>ReadonlyArray<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<unknown, unknown> | 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<unknown, unknown>, any, any>>
>(
loggers: const Loggers extends ReadonlyArray<Logger<unknown, unknown> | Effect.Effect<Logger<unknown, unknown>, any, any>>loggers: function (type parameter) Loggers in <const Loggers extends ReadonlyArray<Logger<unknown, unknown> | Effect.Effect<Logger<unknown, unknown>, any, any>>>(loggers: Loggers, options?: {
readonly mergeWithExisting?: boolean | undefined;
} | undefined): Layer.Layer<never, Loggers extends readonly [] ? never : Effect.Error<Loggers[number]>, Exclude<Loggers extends readonly [] ? never : Effect.Services<Loggers[number]>, Scope.Scope>>
Loggers,
options: | {
readonly mergeWithExisting?:
| boolean
| undefined
}
| undefined
options?: { readonly mergeWithExisting?: boolean | undefinedmergeWithExisting?: boolean | undefined } | undefined
): import LayerLayer.interface Layer<in ROut, out E = never, out RIn = never>A Layer describes how to build one or more services for dependency injection.
When to use
Use to model construction of application services for dependency injection,
especially when services have dependencies, can fail during construction, or
need scoped setup and release.
Details
A Layer<ROut, E, RIn> represents ROut as the services this layer
provides, E as the possible errors during layer construction, and RIn as
the services this layer requires as dependencies.
Layer<
never,
function (type parameter) Loggers in <const Loggers extends ReadonlyArray<Logger<unknown, unknown> | Effect.Effect<Logger<unknown, unknown>, any, any>>>(loggers: Loggers, options?: {
readonly mergeWithExisting?: boolean | undefined;
} | undefined): Layer.Layer<never, Loggers extends readonly [] ? never : Effect.Error<Loggers[number]>, Exclude<Loggers extends readonly [] ? never : Effect.Services<Loggers[number]>, Scope.Scope>>
Loggers extends readonly [] ? never : import EffectEffect.type Error<T> = T extends Effect.Effect<
infer _A,
infer _E,
infer _R
>
? _E
: never
Extracts the error type from an Effect.
When to use
Use to derive the error type from an existing Effect type when declaring
helper types, wrappers, or APIs that preserve the effect's failure channel.
Details
Non-Effect inputs resolve to never.
Error<function (type parameter) Loggers in <const Loggers extends ReadonlyArray<Logger<unknown, unknown> | Effect.Effect<Logger<unknown, unknown>, any, any>>>(loggers: Loggers, options?: {
readonly mergeWithExisting?: boolean | undefined;
} | undefined): Layer.Layer<never, Loggers extends readonly [] ? never : Effect.Error<Loggers[number]>, Exclude<Loggers extends readonly [] ? never : Effect.Services<Loggers[number]>, Scope.Scope>>
Loggers[number]>,
type Exclude<T, U> = T extends U
? never
: T
Exclude from T those types that are assignable to U
Exclude<
function (type parameter) Loggers in <const Loggers extends ReadonlyArray<Logger<unknown, unknown> | Effect.Effect<Logger<unknown, unknown>, any, any>>>(loggers: Loggers, options?: {
readonly mergeWithExisting?: boolean | undefined;
} | undefined): Layer.Layer<never, Loggers extends readonly [] ? never : Effect.Error<Loggers[number]>, Exclude<Loggers extends readonly [] ? never : Effect.Services<Loggers[number]>, Scope.Scope>>
Loggers extends readonly [] ? never : import EffectEffect.type Services<T> =
T extends Effect.Effect<
infer _A,
infer _E,
infer _R
>
? _R
: never
Extracts the required services type from an Effect.
When to use
Use to derive the context requirements of a generic or inferred Effect
without restating its R type parameter.
Services<function (type parameter) Loggers in <const Loggers extends ReadonlyArray<Logger<unknown, unknown> | Effect.Effect<Logger<unknown, unknown>, any, any>>>(loggers: Loggers, options?: {
readonly mergeWithExisting?: boolean | undefined;
} | undefined): Layer.Layer<never, Loggers extends readonly [] ? never : Effect.Error<Loggers[number]>, Exclude<Loggers extends readonly [] ? never : Effect.Services<Loggers[number]>, Scope.Scope>>
Loggers[number]>,
import ScopeScope.Scope
>
> =>
import LayerLayer.const effect: {
<I, S>(service: Context.Key<I, S>): <E, R>(
effect: Effect<S, E, R>
) => Layer<I, E, Exclude<R, Scope.Scope>>
<I, S, E, R>(
service: Context.Key<I, S>,
effect: Effect<Types.NoInfer<S>, E, R>
): Layer<I, E, Exclude<R, Scope.Scope>>
}
effect(
const CurrentLoggers: Context.Reference<
ReadonlySet<Logger<unknown, any>>
>
const CurrentLoggers: {
key: string;
Service: {
forEach: (callbackfn: (value: Logger<unknown, any>, value2: Logger<unknown, any>, set: ReadonlySet<Logger<unknown, any>>) => void, thisArg?: any) => void;
has: (value: Logger<unknown, any>) => boolean;
size: number;
entries: () => SetIterator<[Logger<unknown, any>, Logger<unknown, any>]>;
keys: () => SetIterator<Logger<unknown, any>>;
values: () => SetIterator<Logger<unknown, any>>;
union: (other: ReadonlySetLike<U>) => Set<Logger<unknown, any> | U>;
intersection: (other: ReadonlySetLike<U>) => Set<Logger<unknown, any> & U>;
difference: (other: ReadonlySetLike<U>) => Set<Logger<unknown, any>>;
symmetricDifference: (other: ReadonlySetLike<U>) => Set<Logger<unknown, any> | U>;
isSubsetOf: (other: ReadonlySetLike<unknown>) => boolean;
isSupersetOf: (other: ReadonlySetLike<unknown>) => boolean;
isDisjointFrom: (other: ReadonlySetLike<unknown>) => boolean;
};
defaultValue: () => Shape;
of: (this: void, self: ReadonlySet<Logger<unknown, any>>) => ReadonlySet<Logger<unknown, any>>;
context: (self: ReadonlySet<Logger<unknown, any>>) => Context.Context<never>;
use: (f: (service: ReadonlySet<Logger<unknown, any>>) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
useSync: (f: (service: ReadonlySet<Logger<unknown, any>>) => A) => Effect.Effect<A, never, never>;
Identifier: Identifier;
stack: string | 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; <…;
toString: () => string;
toJSON: () => unknown;
}
Context reference containing the active loggers for the current fiber.
Details
By default this set includes the default logger and the tracer logger.
Providing Logger.layer replaces or merges with this set depending on its
options.
Example (Accessing current loggers)
import { Effect, Logger } from "effect"
// Access current loggers from fiber context
const program = Effect.gen(function*() {
const currentLoggers = yield* Effect.service(Logger.CurrentLoggers)
console.log(`Number of active loggers: ${currentLoggers.size}`)
// Add a custom logger to the set
const customLogger = Logger.make((options) => {
console.log(`Custom: ${options.message}`)
})
yield* Effect.log("Hello from custom logger").pipe(
Effect.provide(Logger.layer([customLogger]))
)
})
CurrentLoggers,
withFiber<A, E = never, R = never>(evaluate: (fiber: effect.FiberImpl<unknown, unknown>) => Effect.Effect<A, E, R>): Effect.Effect<A, E, R>withFiber(import effecteffect.const fnUntraced: <Effect.Effect<Logger<unknown, unknown>, any, any>, Set<Logger<unknown, any>>, [fiber: effect.FiberImpl<unknown, unknown>]>(body: (this: unassigned, fiber: effect.FiberImpl<unknown, unknown>) => Generator<Effect.Effect<Logger<unknown, unknown>, any, any>, Set<Logger<unknown, any>>, never>) => (fiber: effect.FiberImpl<unknown, unknown>) => Effect.Effect<Set<Logger<unknown, any>>, any, any> (+41 overloads)fnUntraced(function*(fiber: effect.FiberImpl<unknown, unknown>(parameter) fiber: {
id: number;
interruptible: boolean;
currentOpCount: number;
currentLoopCount: number;
_stack: Array<Primitive>;
_observers: Array<(exit: Exit.Exit<A, E>) => void>;
_exit: Exit.Exit<A, E> | undefined;
_currentExit: Exit.Exit<A, E> | undefined;
_children: Set<FiberImpl<any, any>> | undefined;
_interruptedCause: Cause.Cause<never> | undefined;
_yielded: Exit.Exit<any, any> | (() => void) | undefined;
context: Context.Context<never>;
currentScheduler: Scheduler.Scheduler;
currentTracerContext: Tracer.Tracer["context"];
currentSpan: Tracer.AnySpan | undefined;
currentLogLevel: LogLevel.LogLevel;
minimumLogLevel: LogLevel.LogLevel;
currentStackFrame: StackFrame | undefined;
runtimeMetrics: Metric.FiberRuntimeMetricsService | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
_dispatcher: Scheduler.SchedulerDispatcher | undefined;
currentDispatcher: SchedulerDispatcher;
getRef: <X>(ref: Context.Reference<X>) => X;
addObserver: (cb: (exit: Exit<unknown, unknown>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<unknown, unknown> | undefined;
evaluate: (effect: Primitive) => void;
runLoop: (effect: Primitive) => Exit<unknown, unknown> | typeof Yield;
getCont: <S extends contA | contE>(symbol: S) => (Primitive & Record<S, (value: any, fiber: effect.FiberImpl) => Primitive>) | undefined;
yieldWith: (value: Exit.Exit<any, any> | (() => void)) => Yield;
children: () => Set<Fiber.Fiber<any, any>>;
pipe: () => unknown;
setContext: (context: Context.Context<never>) => void;
currentSpanLocal: Span | undefined;
}
fiber) {
const const currentLoggers: Set<
Logger<unknown, any>
>
currentLoggers = new var Set: SetConstructor
new <Logger<unknown, any>>(iterable?: Iterable<Logger<unknown, any>> | null | undefined) => Set<Logger<unknown, any>> (+1 overload)
Set(options: | {
readonly mergeWithExisting?:
| boolean
| undefined
}
| undefined
options?.mergeWithExisting?: boolean | undefinedmergeWithExisting === true ? fiber: effect.FiberImpl<unknown, unknown>(parameter) fiber: {
id: number;
interruptible: boolean;
currentOpCount: number;
currentLoopCount: number;
_stack: Array<Primitive>;
_observers: Array<(exit: Exit.Exit<A, E>) => void>;
_exit: Exit.Exit<A, E> | undefined;
_currentExit: Exit.Exit<A, E> | undefined;
_children: Set<FiberImpl<any, any>> | undefined;
_interruptedCause: Cause.Cause<never> | undefined;
_yielded: Exit.Exit<any, any> | (() => void) | undefined;
context: Context.Context<never>;
currentScheduler: Scheduler.Scheduler;
currentTracerContext: Tracer.Tracer["context"];
currentSpan: Tracer.AnySpan | undefined;
currentLogLevel: LogLevel.LogLevel;
minimumLogLevel: LogLevel.LogLevel;
currentStackFrame: StackFrame | undefined;
runtimeMetrics: Metric.FiberRuntimeMetricsService | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
_dispatcher: Scheduler.SchedulerDispatcher | undefined;
currentDispatcher: SchedulerDispatcher;
getRef: <X>(ref: Context.Reference<X>) => X;
addObserver: (cb: (exit: Exit<unknown, unknown>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<unknown, unknown> | undefined;
evaluate: (effect: Primitive) => void;
runLoop: (effect: Primitive) => Exit<unknown, unknown> | typeof Yield;
getCont: <S extends contA | contE>(symbol: S) => (Primitive & Record<S, (value: any, fiber: effect.FiberImpl) => Primitive>) | undefined;
yieldWith: (value: Exit.Exit<any, any> | (() => void)) => Yield;
children: () => Set<Fiber.Fiber<any, any>>;
pipe: () => unknown;
setContext: (context: Context.Context<never>) => void;
currentSpanLocal: Span | undefined;
}
fiber.FiberImpl<X>(ref: Context.Reference<X>): XgetRef(import effecteffect.const CurrentLoggers: Context.Reference<
ReadonlySet<Logger<unknown, any>>
>
const CurrentLoggers: {
key: string;
Service: {
forEach: (callbackfn: (value: Logger<unknown, any>, value2: Logger<unknown, any>, set: ReadonlySet<Logger<unknown, any>>) => void, thisArg?: any) => void;
has: (value: Logger<unknown, any>) => boolean;
size: number;
entries: () => SetIterator<[Logger<unknown, any>, Logger<unknown, any>]>;
keys: () => SetIterator<Logger<unknown, any>>;
values: () => SetIterator<Logger<unknown, any>>;
union: (other: ReadonlySetLike<U>) => Set<Logger<unknown, any> | U>;
intersection: (other: ReadonlySetLike<U>) => Set<Logger<unknown, any> & U>;
difference: (other: ReadonlySetLike<U>) => Set<Logger<unknown, any>>;
symmetricDifference: (other: ReadonlySetLike<U>) => Set<Logger<unknown, any> | U>;
isSubsetOf: (other: ReadonlySetLike<unknown>) => boolean;
isSupersetOf: (other: ReadonlySetLike<unknown>) => boolean;
isDisjointFrom: (other: ReadonlySetLike<unknown>) => boolean;
};
defaultValue: () => Shape;
of: (this: void, self: ReadonlySet<Logger<unknown, any>>) => ReadonlySet<Logger<unknown, any>>;
context: (self: ReadonlySet<Logger<unknown, any>>) => Context.Context<never>;
use: (f: (service: ReadonlySet<Logger<unknown, any>>) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
useSync: (f: (service: ReadonlySet<Logger<unknown, any>>) => A) => Effect.Effect<A, never, never>;
Identifier: Identifier;
stack: string | 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; <…;
toString: () => string;
toJSON: () => unknown;
}
CurrentLoggers) : [])
for (const const logger:
| Logger<unknown, unknown>
| Effect.Effect<
Logger<unknown, unknown>,
any,
any
>
logger of loggers: const Loggers extends ReadonlyArray<Logger<unknown, unknown> | Effect.Effect<Logger<unknown, unknown>, any, any>>loggers) {
const currentLoggers: Set<
Logger<unknown, any>
>
currentLoggers.Set<Logger<unknown, any>>.add(value: Logger<unknown, any>): Set<Logger<unknown, any>>Appends a new element with a specified value to the end of the Set.
add(function isEffect(u: unknown): u is Effect.Effect<any, any, any>isEffect(const logger:
| Logger<unknown, unknown>
| Effect.Effect<
Logger<unknown, unknown>,
any,
any
>
logger) ? yield* const logger: Effect.Effect<
Logger<unknown, unknown>,
any,
any
>
const logger: {
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;
}
logger : const logger: Logger<unknown, unknown>const logger: {
log: (options: Options<unknown>) => unknown;
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; <…;
}
logger)
}
return const currentLoggers: Set<
Logger<unknown, any>
>
currentLoggers
}))
)