Skip to content

Tracing Propagator

This article mainly introduces the products of multiple tracing stacks, and how to realize tracing information propagation them in distributed services.

The transparent transmission protocol, also known as the propagation protocol, is implemented by adding specific header information (generally referring to HTTP headers) in service requests and responses. When a service requests another service, it carries specific request headers. When the next hop receives the request, it obtains the specific link information from the request header and inherits it, and continues to propagate backward until the end of the link. In this way, the entire call chain can be correlated.

Common propagation protocols

The following is a brief introduction to the differences between these transparent transmission protocols in the HTTP header:

Trace Context

Trace Context is a trace protocol standardized by W3C, which defines two HTTP header fields: traceparent and tracestate:

  • traceparent contains basic information about the current trace, such as SpanID and ParentSpanID, etc., for example: traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
  • tracestate is used to pass metadata related to the trace. For example: tracestate: congo=t61rcWkgMzE

B3/B3Multi

B3 is a popular tracking protocol that defines several HTTP header fields to identify tracking information. The B3Multi transparent transmission protocol is an extension of the B3 protocol. The commonly used fields are: X-B3-TraceId, X-B3-SpanId, X-B3-ParentSpanId, X-B3-Sampled, X -B3-Flags etc.

Jaeger

Jaeger is a distributed tracing system that defines several HTTP header fields for passing trace information. Commonly used fields are: uber-trace-id, jaeger-baggage, etc.

OpenTracing

OpenTracing is a transparent transmission protocol of OpenTelemetry, which defines multiple HTTP header fields for transmitting link information:

  • ot-tracer-traceid: used to pass the link ID, indicating a complete request link
  • ot-tracer-spanid: used to pass the ID of the current span, representing a single operation or event
  • ot-tracer-sampled: used to indicate whether to sample the request to decide whether to record the trace information of the request

Datadog

Datadog is a distributed tracing system that defines several HTTP header fields for passing trace information. Commonly used fields are: x-datadog-trace-id, x-datadog-parent-id, etc.

Baggage

Baggage is a concept introduced by the Jaeger tracking system, which is used to transfer business-related context information. Baggage is passed through the HTTP header field x-b3-baggage-<key>, where key is the key of the business context.

The real meaning of Baggage is to propagate key-value pairs of the key:value nature, which is often used to propagate AppID, Host-Name, Host-IP, etc.

Attention

It should be noted that the specific implementation and usage of these transparent transmission protocols may be slightly different, but they all aim to pass tracking information and context information between different services through HTTP header fields to achieve distributed tracking and continuous sex.

Link manufacturers and product introduction

Products and manufacturers:

Products Manufacturers Supported Languages
OpenTelemetry CNCF Java, Python, Go, JavaScript, .NET, Ruby, PHP, Erlang, Swift, Rust, C++, etc.
DDTrace Datadog Java, Python, Go, Ruby, JavaScript, PHP, .NET, Scala, Objective-C, Swift, etc.
SkyWalking Apache SkyWalking Java, .NET, Node.js, PHP, Python, Go, Ruby, Lua, OAP, etc.
Zipkin OpenZipkin Java, Node.js, Ruby, Go, Scala, Python, etc.
Jaeger CNCF Java, Python, Go, C++, C#, Node.js, etc.

The open source address of the product:

Product transparent transmission protocol

OpenTelemetry

List of tracing transparent transmission protocols supported by OTEL:

Propagator List Reference
tracecontext W3C Trace Context
baggage W3C Baggage
b3 B3
b3multi B3Multi
jaeger Jaeger
xray AWS X-Ray
opentracing OpenTracing

Example format of distributed link header information in transparent transmission:

# Example of command line injection (multiple communication protocols are separated by commas)
-Dotel.propagators="tracecontext,baggage"

# Environment variable injection example (Linux)
export OTEL_PROPAGATORS="tracecontext, baggage"

# Environment variable injection example (Windows)
$env:OTEL_PROPAGATORS="tracecontext,baggage"

Datadog

Supported languages Transparent protocol support Commands
Node.js datadog/b3multi/tracecontext/b3/none DD_TRACE_PROPAGATION_STYLE (default datadog)
C++ datadog/b3multi/b3/none DD_TRACE_PROPAGATION_STYLE (default datadog)
.NET datadog/b3multi/tracecontext/none DD_TRACE_PROPAGATION_STYLE (default datadog)
Java datadog/b3multi/tracecontext/none DD_TRACE_PROPAGATION_STYLE (default tracecontext,datadog)

Here none means that tracing protocol transparent transmission is not set.

DD_TRACE_PROPAGATION_STYLE

Datadog tracing can make inbound settings on the behavior of protocol transparent transmission, that is, whether to inherit the upstream protocol and whether to transparently transmit its own protocol to the downstream. It is controlled separately by the following two environment variables:

  • Inbound control: export DD_TRACE_PROPAGATION_STYLE_EXTRACT=<XXX>
  • Outbound control: export DD_TRACE_PROPAGATION_STYLE_INJECT=<YYY>
  • It is also possible to control both inbound and outbound via a single ENV: export DD_TRACE_PROPAGATION_STYLE="tracecontext,datadog"

Example:

# Inbound will inherit X-Datadog-* and X-B3-* headers (if any),
# X-Datadog-* and X-B3-* request headers will be carried when outbound
$ export DD_TRACE_PROPAGATION_STYLE="datadog,b3" ...
Attention

After version V1.7.0, the default support protocol is changed to DD_TRACE_PROPAGATION_STYLE="tracecontext,datadog", B3 has been deprecated, please use B3multi.

For more language examples, see here.

SkyWalking

SkyWalking's own protocol (SW8)

Zipkin

see here

Jaeger

All supported protocols:

Multi-link series

Request header and vendor support list:

W3C b3multi Jaeger OpenTracing Datadog sw8
HTTP Header tracecontext/tracestate X-B3-* uber-trace-id ot-tracer-* x-datadog-* xxx-xxx-xxx-xxx
OpenTelemetry ✔ ✔ ✔ ✔ ✔ ✖
Datadog ✔ ✔ ✖ ✖ ✔ ✖
SkyWalking ✖ ✖ ✖ ✖ ✖ ✔
Zipkin ✖ ✔ ✖ ✖ ✖ ✖
Jaeger ✔ ✔ ✔ ✖ ✖ ✖

According to the specific manufacturer's tools used, the corresponding transparent transmission protocol can be used to realize link series connection and ensure link integrity.

Concatenation Example

Here is an example to illustrate the concatenation of DDTrace and OpenTelemetry link data. It can be seen from the above table that both DDTrace and OpenTelemetry support the W3C Trace Context protocol, and link concatenation can be realized through this protocol.

  • TraceID in DDTrace is a 64-bit int string, and SpanID and ParentID are also 64-bit int
  • TraceID in OTEL is a 128-bit hexadecimal int string, and SpanID and ParentID are 64-bit int strings

If the two want to associate TraceID, DDTrace needs to be upgraded to 128 bits.

No matter which one is the initiator of the request, DDTrace needs to enable 128bit TraceID support (dd.trace.128.bit.traceid.generation.enabled):

# DDTrace start example
$ java -javaagent:/usr/local/ddtrace/dd-java-agent.jar\
  -Ddd.service.name=client \
  -Ddd.trace.128.bit.traceid.generation.enabled=true \
  -Ddd.trace.propagation.style=tracecontext\
  -jar springboot-client.jar

# OTEL start example
$ java -javaagent:/usr/local/ddtrace/opentelemetry-javaagent.jar\
  -dotel.service.name=server\
  -jar springboot-server.jar

The client will send an HTTP request to the server, and DDTrace will pass the link information in the tracecontext request header to the server

However, in the "service call relationship", the data from the two tools cannot be connected. This is because the SpanIDs of both parties are not uniform. DDTrace is a decimal string of numbers, while OpenTelemetry is a hexadecimal number character. string. To do this, you need to modify the configuration in the ddtrace collector and release compatible_otel in ddtrace.conf:

  ## compatible otel: It is possible to compatible OTEL Trace with DDTrace trace.
  ## make span_id and parent_id to hex encoding.
  compatible_otel=true

After compatible_otel=true, all DDTrace span_id and parent_id will become hexadecimal numeric strings.

Convert span_id from digital to hexadecimal

In the logging, the SpanId in DDTrace is still in decimal, you need to extract span_id in the Pipeline for collecting logs and convert it into a hexadecimal number string (the original logging text will not be modified):

# convert string to int64
fn parse_int(val: str, base: int) int64

# convert int64 to string
fn format_int(val: int64, base: int) str

So far, DDTrace and OTEL have been connected in series on the link, and the service call relationship and logs can also be connected in series:

Link Details
Link Details

Feedback

Is this page helpful? ×