๐Ÿชก Manual context propagation

Propagate context manually to tie together end-to-end flows in your distributed application when the automatic instrumentation doesn't provide full coverage.

OpenTelemetry's context, leveraged by Helios to track service operations and application flows, can be propagated manually to any DTO (data transfer object), and made available at any subsequent stage of the event's life span.

Manual context propagation consists of:

  1. Injecting the active context to the DTO, and then
  2. Extracting the same context

With manual context propagation any application can benefit from E2E distributed tracing across its flows.

Injection

Assuming we want to inject the active context to a DTO named carrier:

const { context, propagation } = require('@opentelemetry/api');

// "carrier" can be any "object" (i.e. any dictionary of key-value pairs):
const carrier = {};

// This adds to "carrier" a new key named "traceparent", whose value is the active context:
propagation.inject(context.active(), carrier);
import { context, propagation } from '@opentelemetry/api';

// "carrier" can be any "object" (i.e. any dictionary of key-value pairs):
const carrier: any = {};

// This adds to "carrier" a new key named "traceparent", whose value is the active context:
propagation.inject(context.active(), carrier);
from opentelemetry import context, propagate

# "carrier" can be any "dict" (i.e. any dictionary of key-value pairs):
carrier = {}

# This adds to "carrier" a new key named "traceparent", whose value is the current context:
propagate.inject(carrier, context.get_current())

Extraction

Now let's extract the same context, and propagate it to the rest of the application's flow:

const { context, propagation } = require('@opentelemetry/api');

// "carrier" is an "object" that has a key named "traceparent", whose value is the context:
const extractedContext = propagation.extract(context.active(), carrier);

// Propagate the extracted context to a subsequent operation:
context.with(extractedContext, () => {
    // Your synchronous business logic goes here.
});

// Or:
await context.with(extractedContext, async () => {
    // Your asynchronous business logic goes here.
});
import { context, propagation } from '@opentelemetry/api';

// "carrier" is an "object" that has a key named "traceparent", whose value is the context:
const extractedContext = propagation.extract(context.active(), carrier);

// Propagate the extracted context to a subsequent operation:
context.with(extractedContext, () => {
    // Your synchronous business logic goes here.
});

// Or:
await context.with(extractedContext, async () => {
    // Your asynchronous business logic goes here.
});
from opentelemetry import context, propagate

# "carrier" is a "dict" that has a key named "traceparent", whose value is the context:
extracted_context = propagate.extract(carrier, context.get_current())

# Propagate the extracted context to a subsequent operation:
token = context.attach(extracted_context)
# Your business logic goes here.
context.detach(token)

๐Ÿ“˜

Learn more on manual context propagation and going beyond trivial examples in this blog post.