Skip to content

Trace: exported spans never carry parent_span_id, so traces are flat #55

Description

@jtakakura

The OTLP span exporter hard-codes an empty parent_span_id:

.parent_span_id = (""), // TODO: get from parent context

The root cause is one layer up: api.trace.Span has no field for the parent's span id, so the exporter has nothing to read. Tracer.startSpan takes the parent's SpanContext from options.parent_context, keeps its trace_id, and discards its span_id:

// Determine trace ID based on parent
if (parent_span_context) |parent_sc| {
trace_id = parent_sc.trace_id;
span_id = self.provider.id_generator.newSpanID(trace_id);
} else {

Effect: spans created with parent_context share the parent's trace_id (verified at 8b99dba with zig 0.16.0: one parent, four children, stdout exporter), but every span arrives as a root, so backends show a flat trace. The stdout exporter's SerializableSpan has no parent field either; no configuration exports the parent today. I did not run an OTLP round trip; that half of the claim is from the exporter source.

The // TODO: get from parent context comment dates back to the first exporter implementation (zig-o11y/opentelemetry-sdk fa00ee7, 2025-09-09); I found no issue tracking it here or in zig-o11y.

Proposed fix:

  1. add parent_span_id: ?SpanID = null to api.trace.Span
  2. set it in Tracer.startSpan where the parent's trace_id is already copied
  3. emit it in spanToOTLP (SpanID.toBinary() is already used for the span's own id) and add the field to SerializableSpan

One spot that is easy to miss: BatchingProcessor.cloneSpan copies fields one by one (span_processor.zig L375), so it needs the new field too, ideally with a test asserting the parent survives cloning.

Related: #54 fixes how ids are encoded in OTLP/JSON; this issue is about the field never being populated. Both are needed for a correct parentSpanId on the wire.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsdktrace

    Type

    No type

    Projects

    Status
    In progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions