Overview
In a distributed system:- Producers initiate traces by creating new trace contexts
- Consumers receive trace contexts, parse them, and create child spans for downstream calls
- Both use
traceparentandtracestateheaders to propagate context
Producer: Starting a Trace
A producer creates a new trace context and sends it to a downstream service.By default,
traceparent.make() creates a sampled trace with both FLAG_SAMPLE and FLAG_RANDOM set.Consumer: Continuing a Trace
A consumer receives trace context headers, parses them, and creates child spans for downstream calls.Update tracestate with vendor data
Add or update vendor-specific information in the tracestate:The
set() method will:- Update the value if the key exists (and move it to the front)
- Prepend a new key-value pair if the key doesn’t exist
- Remove the oldest entry if the tracestate is full (32 entries)
Create a child span for downstream calls
Use the The
child() method to create a new span with a new parent-id while preserving the trace-id:child() method:- Keeps the same
trace-id(maintains the trace chain) - Generates a new
parent-id(creates a new span) - Copies all existing flags (preserves sampling decisions)
Complete Example
Here’s a complete example showing both producer and consumer:Trace Anatomy
Understanding the structure of a traceparent helps visualize the producer/consumer flow:Best Practices
Always validate parsed traceparent
Always validate parsed traceparent
The
parse() function returns null if the header is invalid:Only parse tracestate if traceparent is valid
Only parse tracestate if traceparent is valid
Per the W3C specification, tracestate should only be processed if traceparent is valid:
Preserve trace context in async operations
Preserve trace context in async operations
When performing multiple async operations, ensure you use the same parent context:
Related
Sampling
Control which traces are collected
Trace Flags
Understand and manipulate trace flags