A link from the current Span to another SpanContext (spec
trace/api.md §Link, Status: Stable, L803-L834).
A Link pairs a SpanContext identifying the target span with a
set of attributes describing the relationship. Linked spans may
be part of the same trace or a different trace (spec L805-L807).
Per spec L815-L821 the API accepts the linked SpanContext and
optional Attributes either as individual parameters or as an
immutable object encapsulating them — this struct is that
immutable object. Construct with a struct literal:
%Otel.API.Trace.Link{context: span_ctx}
%Otel.API.Trace.Link{context: span_ctx, attributes: %{"key" => "val"}}No dedicated constructor is provided; there is no construction-
time normalisation or opaque boundary that would require one
(same rationale as Otel.API.InstrumentationScope).
Per spec L853 Links are immutable; an Elixir struct satisfies that naturally. All functions on this module are safe for concurrent use (spec L843-L853 "Link [SHOULD be] documented ... safe for concurrent use by default").
Note: spec #### Specifying links (L442-L447) is a separate
concern — it describes how Link values are passed at Span
creation, which is the Span builder's responsibility, not this
type module's.
Design notes
Zero-TraceId / zero-SpanId links permitted by design
Spec L820-L823 SHOULD:
"Implementations SHOULD record links containing SpanContext with empty TraceId or SpanId (all zeros) as long as either the attribute set or TraceState is non-empty."
This struct does no validation on context — any
SpanContext, including one with all-zero trace_id or
span_id, is accepted. Validating at this type module
would pre-reject spec-compliant Links whose recording
decision belongs to the SDK.
The SHOULD's "as long as attributes or TraceState is
non-empty" condition is a recording decision — it
belongs to the SDK's span-storage path (the module
registered via Otel.API.Trace.Span.set_module/1), where
the full Link data (context + attributes + tracestate) is
available and where the policy "retain or drop" applies.
API callers can construct any Link; the SDK handles
recording per SHOULD. A valid?/1 / should_record?/1
predicate is intentionally not exposed on this module
because the "should record" rule depends on SDK policy,
not struct shape.
References
- OTel Trace API §Link:
opentelemetry-specification/specification/trace/api.mdL803-L834
Summary
Types
@type primitive_any() :: primitive() | [primitive_any()] | %{required(String.t()) => primitive_any()}
@type t() :: %Otel.API.Trace.Link{ attributes: %{required(String.t()) => primitive_any()}, context: Otel.API.Trace.SpanContext.t() }
A Link struct (spec trace/api.md §Link, L809-L813).
Fields:
context— theSpanContextof the Span being linked to. Zero-TraceId / zero-SpanId contexts are permitted; see the module's## Design notesfor the rationale.attributes— zero or more attributes describing the relationship. Values follow OTel attribute rules (primitives and homogeneous arrays; no maps, no heterogeneous arrays).