Otel.SDK.Trace.SpanStorage (otel v0.2.0)

Copy Markdown View Source

ETS-backed storage for active spans.

A GenServer that owns the ETS table. The table is public with write_concurrency and read_concurrency so any process can read/write spans without going through this server.

Design notes

ETS layout

A single named table (Otel.SDK.Trace.SpanStorage) stores every active span. The table key is the 64-bit span_id, giving O(1) lookup and removal. The value is the internal Otel.SDK.Trace.Span struct carrying all mutable fields (name, kind, attributes, events, links, status, trace/span identifiers, timestamps, recording flag, instrumentation scope).

The GenServer's sole job is to own the table so that it lives with the SDK supervisor and dies with it. Reads and writes happen directly against the ETS table from whichever process is holding the span — the GenServer is not on the hot path for any operation.

Concurrency model

Spans are typically mutated only by the process that created them, reached through the current Ctx. write_concurrency + read_concurrency allow lock-free parallel access from multiple processes on the rare cross-process path (e.g. a span handed across Task.async/1). No additional synchronisation is required.

Lifecycle

StepOperationETS call
start_spaninsert structinsert/2
set_attribute, add_event, ...mutate in placeinsert/2
end_spanremove and hand to processorstake/1

take/1 is used rather than lookup + delete so the span leaves the table atomically — no window in which a second reader could see an ended-but-still-stored span.

Summary

Functions

Returns a specification to start this module under a supervisor.

Looks up a span by span_id.

Inserts a span into the table.

Returns the ETS table name.

Removes and returns a span by span_id.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

get(span_id)

@spec get(span_id :: Otel.API.Trace.SpanId.t()) :: Otel.SDK.Trace.Span.t() | nil

Looks up a span by span_id.

insert(span)

@spec insert(span :: Otel.SDK.Trace.Span.t()) :: true

Inserts a span into the table.

start_link(opts)

@spec start_link(opts :: keyword()) :: GenServer.on_start()

table()

@spec table() :: atom()

Returns the ETS table name.

take(span_id)

@spec take(span_id :: Otel.API.Trace.SpanId.t()) :: Otel.SDK.Trace.Span.t() | nil

Removes and returns a span by span_id.