Skip to main content

Context Propagation

Overview

Signadot can dynamically route http and gRPC requests to specific versions of the destination Service based on sidecars or a Service Mesh. A specific request header value is used to determine where to route a request. By default requests are routed to the baseline version of Services. If the header contains context for a specific Sandbox, then the request is routed to the forked version of the Service in that Sandbox.

Consider an example where you have Services A, B and C and we have a fork, Service B" in a Sandbox. In the request flow diagram shown below, the dotted orange lines show a request that includes a header with a reference to the Sandbox. This request is routed to the forked version Service B" that's part of the Sandbox. All requests without this header, will flow through Service B.

For this to work, a pre-requisite is for Service A to propagate specific request headers from the incoming requests to all outgoing requests. This is called context propagation. The sections below detail how Signadot makes use of context propagation and how to implement context propagation in your Services.

Header Propagation

Header Injection

When Signadot receives a request on a Sandbox Endpoint, our proxy injects header values to identify the desired sandbox before forwarding the request on to your service.

The goal of context propagation is to ensure that this sandbox metadata survives every step of the subsequent chain of service-to-service requests, so that request routing can occur at any step.

To maximize the chances of this metadata being propagated automatically, we inject multiple, redundant copies in formats that common distributed tracing libraries use for "baggage", which is the conventional name for this kind of arbitrary metadata propagation.

Setting up Context Propagation

Context propagation is commonly achieved using distributed tracing libraries because these libraries can often automatically instrument your code with minimal changes. They do this with request middleware layers that extract data from certain headers in all incoming requests, propagate that data throughout the function call stack, and add the same header values to all outgoing requests made from within that call stack.

Signadot supports the following header formats in HTTP 1/2 and gRPC and the corresponding tracing libraries.

OpenTelemetry Tracing

There are two mechanisms of propagation that are supported from the OpenTelemetry specification:

In both of these cases, a key named sd-sandbox is used to persist information pertaining to Sandboxes. If you're making use of OpenTelemetry instrumentation in your services, baggage and tracestate headers are propagated automatically.

Jaeger Tracing

A header named uberctx-sd-sandbox is expected to be propagated by your services. If you're making use of Jaeger instrumentation in your services, headers in this format are propagated automatically.

Datadog Tracing

A header named ot-baggage-sd-sandbox is expected to be propagated by your services. If you're using Datadog's Go language instrumentation libraries, headers in this format are propagated automatically. Support in other languages depends on the library being used and the mode in which it's used.

Custom Instrumentation

If you are not using the above libraries, we recommend that you make use of the baggage header as described in the W3C Baggage Specification. Services would need to propagate this header from each incoming request to any outgoing requests the original handler makes.

The headers that will be set on the entry-point service when using a Signadot preview URL will be in the following format and the application must propagate this header as-is (or with modifications according to the W3C spec) to other services in the system.

baggage: sd-sandbox=<sandbox-id>

Header Propagation Examples

Sample code for implementing header propagation in various languages using OpenTelemetry can be found in this GitHub Repository.