๐Ÿชก 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. This is another mechanism to put together distributed traces across microservices, so you can see all the operations carried out as part of the flow in a single trace.

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())
import (
	"context"
	"go.opentelemetry.io/otel"
)

// carrier should implement the `TextMapCarrier` interface (https://github.com/open-telemetry/opentelemetry-go/blob/ef0cdebc945d96b0b0050e45ae820ca8894993b6/propagation/propagation.go#L23)
carrier := make(map[string][]string)

// The current context
ctx := context.Background()

// Propagator should implement the `TextMapPropagator` interface (https://github.com/open-telemetry/opentelemetry-go/blob/ef0cdebc945d96b0b0050e45ae820ca8894993b6/propagation/propagation.go#L93)
propagator := otel.GetTextMapPropagator()
propagator.Inject(ctx, carrier)

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)
import (
	"context"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/propagation"
)

// carrier should implement the `TextMapCarrier` interface (https://github.com/open-telemetry/opentelemetry-go/blob/ef0cdebc945d96b0b0050e45ae820ca8894993b6/propagation/propagation.go#L23)
carrier := make(map[string][]string)

// Propagator should implement the `TextMapPropagator` interface (https://github.com/open-telemetry/opentelemetry-go/blob/ef0cdebc945d96b0b0050e45ae820ca8894993b6/propagation/propagation.go#L93)
propagator := otel.GetTextMapPropagator()
extractedContext := propagator.Extract(ctx, carrier)

๐Ÿ‘

All set

You can now benefit from complete visibility into E2E flows in your distributed application.