(name: string, options?: SpanOptions): Layer<Tracer.ParentSpan>Constructs a new Layer which creates a span and registers it as the current
parent span.
Details
This allows you to create a traced scope for layer construction, making all
operations within the layer constructor part of the same trace span. The span
is automatically ended when the layer's scope is closed. If onEnd is
provided, it receives the span and the layer scope's exit value when the span
ends.
Example (Tracing layer construction with a span)
import { Console, Context, Effect, Layer } from "effect"
import type { Tracer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
// Create a traced layer - all operations performed during construction of
// the `Database` service are part of the "database-init" span
const databaseLayer = Layer.effect(Database, Effect.gen(function*() {
// These operations are traced under "database-init" span
yield* Effect.log("Connecting to database")
yield* Effect.sleep("100 millis")
yield* Effect.log("Database connected")
const parentSpan = yield* Effect.currentParentSpan
yield* Console.log((parentSpan as Tracer.Span).name) // "database-init"
return {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`Result: ${sql}`))
}
})).pipe(Layer.provide(Layer.span("database-init")))
// Can also use the `onEnd` callback to execute logic when the span ends
const tracedLayer = Layer.span("service-initialization", {
attributes: { version: "1.0.0" },
onEnd: (span, exit) =>
Effect.sync(() => {
console.log(`Span ${span.name} ended with:`, exit._tag)
})
})export const const span: (
name: string,
options?: SpanOptions
) => Layer<Tracer.ParentSpan>
Constructs a new Layer which creates a span and registers it as the current
parent span.
Details
This allows you to create a traced scope for layer construction, making all
operations within the layer constructor part of the same trace span. The span
is automatically ended when the layer's scope is closed. If onEnd is
provided, it receives the span and the layer scope's exit value when the span
ends.
Example (Tracing layer construction with a span)
import { Console, Context, Effect, Layer } from "effect"
import type { Tracer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
// Create a traced layer - all operations performed during construction of
// the `Database` service are part of the "database-init" span
const databaseLayer = Layer.effect(Database, Effect.gen(function*() {
// These operations are traced under "database-init" span
yield* Effect.log("Connecting to database")
yield* Effect.sleep("100 millis")
yield* Effect.log("Database connected")
const parentSpan = yield* Effect.currentParentSpan
yield* Console.log((parentSpan as Tracer.Span).name) // "database-init"
return {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`Result: ${sql}`))
}
})).pipe(Layer.provide(Layer.span("database-init")))
// Can also use the `onEnd` callback to execute logic when the span ends
const tracedLayer = Layer.span("service-initialization", {
attributes: { version: "1.0.0" },
onEnd: (span, exit) =>
Effect.sync(() => {
console.log(`Span ${span.name} ended with:`, exit._tag)
})
})
span = (
name: stringname: string,
options: SpanOptionsoptions?: SpanOptions
): 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<import TracerTracer.class ParentSpanclass ParentSpan {
Service: Service;
key: Identifier;
}
Context service containing the Span or ExternalSpan to use as the parent
of newly-created child spans.
Example (Accessing the parent span)
import { Effect, Tracer } from "effect"
// Access the parent span from the context
const program = Effect.gen(function*() {
const parentSpan = yield* Effect.service(Tracer.ParentSpan)
console.log(`Parent span: ${parentSpan.spanId}`)
})
ParentSpan> => {
options: SpanOptionsoptions = import internalTracerinternalTracer.const addSpanStackTrace: <
A extends Tracer.TraceOptions
>(
options: A | undefined
) => A
addSpanStackTrace(options: SpanOptionsoptions)
return 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(
import TracerTracer.class ParentSpanclass ParentSpan {
key: Identifier;
of: (this: void, self: Tracer.AnySpan) => Tracer.AnySpan;
context: (self: Tracer.AnySpan) => Context.Context<Tracer.ParentSpan>;
use: (f: (service: Tracer.AnySpan) => Effect<A, E, R>) => Effect<A, E, Tracer.ParentSpan | R>;
useSync: (f: (service: Tracer.AnySpan) => A) => Effect<A, never, Tracer.ParentSpan>;
Identifier: Identifier;
Service: Shape;
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 service containing the Span or ExternalSpan to use as the parent
of newly-created child spans.
Example (Accessing the parent span)
import { Effect, Tracer } from "effect"
// Access the parent span from the context
const program = Effect.gen(function*() {
const parentSpan = yield* Effect.service(Tracer.ParentSpan)
console.log(`Parent span: ${parentSpan.spanId}`)
})
ParentSpan,
options: SpanOptions(parameter) options: {
onEnd: ((span: Tracer.Span, exit: Exit.Exit<unknown, unknown>) => Effect<void>) | undefined;
attributes: Record<string, unknown> | undefined;
links: ReadonlyArray<SpanLink> | undefined;
parent: AnySpan | undefined;
root: boolean | undefined;
annotations: Context.Context<never> | undefined;
kind: SpanKind | undefined;
sampled: boolean | undefined;
level: LogLevel | undefined;
captureStackTrace: boolean | LazyArg<string | undefined> | undefined;
}
options?.SpanOptions.onEnd?: ((span: Tracer.Span, exit: Exit.Exit<unknown, unknown>) => Effect<void>) | undefinedRuns when the span associated with the layer ends, which happens when the
layer scope is closed.
onEnd
? import internalEffectinternalEffect.const tap: {
<A, B, E2, R2>(
f: (a: NoInfer<A>) => Effect.Effect<B, E2, R2>
): <E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<A, E | E2, R | R2>
<B, E2, R2>(f: Effect.Effect<B, E2, R2>): <
A,
E,
R
>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<A, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect.Effect<A, E, R>,
f: (a: NoInfer<A>) => Effect.Effect<B, E2, R2>
): Effect.Effect<A, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect.Effect<A, E, R>,
f: Effect.Effect<B, E2, R2>
): Effect.Effect<A, E | E2, R | R2>
}
tap(
import internalEffectinternalEffect.const makeSpanScoped: (
name: string,
options?: Tracer.SpanOptionsNoTrace | undefined
) => Effect.Effect<
Tracer.Span,
never,
Scope.Scope
>
makeSpanScoped(name: stringname, options: SpanOptions(parameter) options: {
onEnd: ((span: Tracer.Span, exit: Exit.Exit<unknown, unknown>) => Effect<void>) | undefined;
attributes: Record<string, unknown> | undefined;
links: ReadonlyArray<SpanLink> | undefined;
parent: AnySpan | undefined;
root: boolean | undefined;
annotations: Context.Context<never> | undefined;
kind: SpanKind | undefined;
sampled: boolean | undefined;
level: LogLevel | undefined;
captureStackTrace: boolean | LazyArg<string | undefined> | undefined;
}
options),
(span: Tracer.Span(parameter) span: {
_tag: "Span";
name: string;
spanId: string;
traceId: string;
parent: Option.Option<AnySpan>;
annotations: Context.Context<never>;
status: SpanStatus;
attributes: ReadonlyMap<string, unknown>;
links: ReadonlyArray<SpanLink>;
sampled: boolean;
kind: SpanKind;
end: (endTime: bigint, exit: Exit.Exit<unknown, unknown>) => void;
attribute: (key: string, value: unknown) => void;
event: (name: string, startTime: bigint, attributes?: Record<string, unknown>) => void;
addLinks: (links: ReadonlyArray<SpanLink>) => void;
}
span) => import internalEffectinternalEffect.const addFinalizer: <R>(
finalizer: (
exit: Exit.Exit<unknown, unknown>
) => Effect.Effect<void, never, R>
) => Effect.Effect<void, never, R | Scope.Scope>
addFinalizer((exit: Exit.Exit<unknown, unknown>exit) => options: SpanOptions(parameter) options: {
onEnd: ((span: Tracer.Span, exit: Exit.Exit<unknown, unknown>) => Effect<void>) | undefined;
attributes: Record<string, unknown> | undefined;
links: ReadonlyArray<SpanLink> | undefined;
parent: AnySpan | undefined;
root: boolean | undefined;
annotations: Context.Context<never> | undefined;
kind: SpanKind | undefined;
sampled: boolean | undefined;
level: LogLevel | undefined;
captureStackTrace: boolean | LazyArg<string | undefined> | undefined;
}
options.SpanOptions.onEnd?: ((span: Tracer.Span, exit: Exit.Exit<unknown, unknown>) => Effect<void>) | undefinedRuns when the span associated with the layer ends, which happens when the
layer scope is closed.
onEnd!(span: Tracer.Span(parameter) span: {
_tag: "Span";
name: string;
spanId: string;
traceId: string;
parent: Option.Option<AnySpan>;
annotations: Context.Context<never>;
status: SpanStatus;
attributes: ReadonlyMap<string, unknown>;
links: ReadonlyArray<SpanLink>;
sampled: boolean;
kind: SpanKind;
end: (endTime: bigint, exit: Exit.Exit<unknown, unknown>) => void;
attribute: (key: string, value: unknown) => void;
event: (name: string, startTime: bigint, attributes?: Record<string, unknown>) => void;
addLinks: (links: ReadonlyArray<SpanLink>) => void;
}
span, exit: Exit.Exit<unknown, unknown>exit))
)
: import internalEffectinternalEffect.const makeSpanScoped: (
name: string,
options?: Tracer.SpanOptionsNoTrace | undefined
) => Effect.Effect<
Tracer.Span,
never,
Scope.Scope
>
makeSpanScoped(name: stringname, options: SpanOptions(parameter) options: {
onEnd: ((span: Tracer.Span, exit: Exit.Exit<unknown, unknown>) => Effect<void>) | undefined;
attributes: Record<string, unknown> | undefined;
links: ReadonlyArray<SpanLink> | undefined;
parent: AnySpan | undefined;
root: boolean | undefined;
annotations: Context.Context<never> | undefined;
kind: SpanKind | undefined;
sampled: boolean | undefined;
level: LogLevel | undefined;
captureStackTrace: boolean | LazyArg<string | undefined> | undefined;
}
options)
)
}