SpanA span created by an Effect tracer. It carries trace identity, parent, annotations, attributes, links, sampling and kind information, lifecycle status, and methods to end the span or add attributes, events, and links.
Example (Working with spans)
import { Context, Exit, Option } from "effect"
import type { Tracer } from "effect"
const attributes = new Map<string, unknown>()
const links: Array<Tracer.SpanLink> = []
let status: Tracer.SpanStatus = {
_tag: "Started",
startTime: 1_000_000_000n
}
const span: Tracer.Span = {
_tag: "Span",
name: "load-user",
spanId: "span-1",
traceId: "trace-1",
parent: Option.none(),
annotations: Context.empty(),
get status() {
return status
},
attributes,
links,
sampled: true,
kind: "internal",
end(endTime, exit) {
status = { _tag: "Ended", startTime: status.startTime, endTime, exit }
},
attribute(key, value) {
attributes.set(key, value)
},
event(name, startTime, eventAttributes = {}) {
console.log(`${name} at ${startTime} with ${Object.keys(eventAttributes).length} attributes`)
},
addLinks(newLinks) {
links.push(...newLinks)
}
}
span.attribute("user.id", "123")
span.end(1_500_000_000n, Exit.succeed("user"))
console.log(span.name) // "load-user"
console.log(span.attributes.get("user.id")) // "123"
console.log(span.status._tag) // "Ended"export interface Span {
readonly Span._tag: "Span"_tag: "Span"
readonly Span.name: stringname: string
readonly Span.spanId: stringspanId: string
readonly Span.traceId: stringtraceId: string
readonly Span.parent: Option.Option<AnySpan>parent: import OptionOption.type Option.Option = /*unresolved*/ anyOption<type AnySpan = Span | ExternalSpanA span value that can participate in tracing, either an Effect-managed
Span or an ExternalSpan propagated from another tracing system.
Example (Accepting any span)
import { Effect, Tracer } from "effect"
// Function that accepts any span type
const logSpan = (span: Tracer.AnySpan) => {
console.log(`Span ID: ${span.spanId}, Trace ID: ${span.traceId}`)
return Effect.succeed(span)
}
// Works with both Span and ExternalSpan
const externalSpan = Tracer.externalSpan({
spanId: "span-123",
traceId: "trace-456"
})
AnySpan>
readonly Span.annotations: Context.Context<never>(property) Span.annotations: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
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;
}
annotations: import ContextContext.type Context.Context = /*unresolved*/ anyContext<never>
readonly Span.status: SpanStatusstatus: type SpanStatus =
| {
_tag: "Started"
startTime: bigint
}
| {
_tag: "Ended"
startTime: bigint
endTime: bigint
exit: Exit.Exit<unknown, unknown>
}
Lifecycle state of a span, where Started records the start time and
Ended records the start time, end time, and exit value with which the span
completed.
Example (Creating span statuses)
import { Exit } from "effect"
import type { Tracer } from "effect"
const startTime = 1_000_000_000n
const endTime = 1_500_000_000n
const startedStatus: Tracer.SpanStatus = {
_tag: "Started",
startTime
}
const endedStatus: Tracer.SpanStatus = {
_tag: "Ended",
startTime,
endTime,
exit: Exit.succeed("result")
}
console.log(startedStatus._tag) // "Started"
console.log(endedStatus.endTime - endedStatus.startTime) // 500000000n
SpanStatus
readonly Span.attributes: ReadonlyMap<string, unknown>attributes: interface ReadonlyMap<K, V>ReadonlyMap<string, unknown>
readonly Span.links: ReadonlyArray<SpanLink>links: interface ReadonlyArray<T>ReadonlyArray<SpanLink>
readonly Span.sampled: booleansampled: boolean
readonly Span.kind: SpanKindkind: type SpanKind =
| "internal"
| "server"
| "client"
| "producer"
| "consumer"
OpenTelemetry-style role describing the kind of operation represented by a
span: internal work, server handling, client calls, producing, or consuming.
Example (Configuring span kinds)
import { Effect } from "effect"
import type { Tracer } from "effect"
// Different span kinds for different operations
const serverSpan = Effect.withSpan("handle-request", {
kind: "server" as Tracer.SpanKind
})
const clientSpan = Effect.withSpan("api-call", {
kind: "client" as Tracer.SpanKind
})
const internalSpan = Effect.withSpan("internal-process", {
kind: "internal" as Tracer.SpanKind
})
SpanKind
Span.end(endTime: bigint, exit: Exit.Exit<unknown, unknown>): voidend(endTime: bigintendTime: bigint, exit: Exit.Exit<unknown, unknown>exit: import ExitExit.type Exit.Exit = /*unresolved*/ anyExit<unknown, unknown>): void
Span.attribute(key: string, value: unknown): voidattribute(key: stringkey: string, value: unknownvalue: unknown): void
Span.event(name: string, startTime: bigint, attributes?: Record<string, unknown>): voidevent(name: stringname: string, startTime: bigintstartTime: bigint, attributes: Record<string, unknown> | undefinedattributes?: type Record<K extends keyof any, T> = {
[P in K]: T
}
Construct a type with a set of properties K of type T
Record<string, unknown>): void
Span.addLinks(links: ReadonlyArray<SpanLink>): voidaddLinks(links: ReadonlyArray<SpanLink>links: interface ReadonlyArray<T>ReadonlyArray<SpanLink>): void
}