Propagation

Context propagation for the JS SDK

Propagation is the mechanism that moves data between services and processes. Although not limited to tracing, it is what allows traces to build causal information about a system across services that are arbitrarily distributed across process and network boundaries.

Context propagation with libraries

For the vast majority of use cases, context propagation is done with instrumentation libraries.

For example, if you have several Node.js services that communicate over HTTP, you can use the express and http instrumentation libraries to automatically propagate trace context across services for you.

It is highly recommend that you use instrumentation libraries to propagate context. Although it is possible to propagate context manually, if your system uses libraries to communicate between services, use a matching instrumentation library to propagate context.

Refer to Libraries to learn more about instrumentation libraries and how to use them.

Manual W3C Trace Context Propagation

In some cases, it is not possible to propagate context with an instrumentation library. There may not be an instrumentation library that matches a library you’re using to have services communicate with one another. Or you many have requirements that instrumentation libraries cannot fulfill, even if they exist.

When you must propagate context manually, you can use the context API.

The following generic example demonstrates how you can propagate trace context manually.

First, on the sending service, you’ll need to inject the current context:

// Sending service
import { context, propagation, trace } from '@opentelemetry/api';
const output = {};

// Serialize the traceparent and tracestate from context into
// an output object.
//
// This example uses the active trace context, but you can
// use whatever context is appropriate to your scenario.
propagation.inject(context.active(), output);

const { traceparent, tracestate } = output;
// You can then pass the traceparent and tracestate
// data to whatever mechanism you use to propagate
// across services.

On the receiving service, you’ll need to extract context (for example, from parsed HTTP headers) and then set them as the current trace context.

// Receiving service
import { context, propagation, trace } from '@opentelemetry/api';

// Assume "input" is an object with 'traceparent' & 'tracestate' keys
const input = {};

// Extracts the 'traceparent' and 'tracestate' data into a context object.
//
// You can then treat this context as the active context for your
// traces.
let activeContext = propagation.extract(context.active(), input);

let tracer = trace.getTracer('app-name');

let span = tracer.startSpan(
  spanName,
  {
    attributes: {},
  },
  activeContext,
);

// Set the created span as active in the deserialized context.
trace.setSpan(activeContext, span);

From there, when you have a deserialized active context, you can create spans that will be a part of the same trace from the other service.

You can also use the Context API to modify or set the deserialized context in other ways.