CONCEPT Cited by 1 source
Async context propagation¶
Definition¶
Async context propagation is the mechanism by which a
distributed-tracing library associates a span (or other
per-request context) with the asynchronous continuation of the
code that started it โ so that spans created inside a
setTimeout, fetch, Promise.then, or similar callback
automatically become children of the current span without the
programmer having to pass the parent span explicitly.
How it works per runtime¶
Node.js: AsyncLocalStorage¶
Node's
AsyncLocalStorage
API (built on async_hooks) provides runtime-native async-
context propagation. OpenTelemetry JS's Node SDK uses it by
default. Calls like:
await tracer.startActiveSpan("name", async () => {
await callOtherFunction(); // callOtherFunction's spans
// auto-parent to "name"
});
work without passing the span explicitly. The async-local store is keyed on the Node.js async-ID tree.
Browser: no native primitive¶
The TC39
AsyncContext proposal
is still in progress. Until it lands, the only equivalent is
Zone.js,
which monkey-patches global
functions (setTimeout, Promise, addEventListener, etc.)
to instrument async scheduling manually.
The cost of automatic propagation¶
- On the server: auto-context is clean; OTel's
startActiveSpanAPI is idiomatic. But migrating from OpenTracing-style manual-span-passing is expensive โ "especially in a large codebase like ours" (Source: sources/2024-07-28-zalando-opentelemetry-for-javascript-observability-at-zalando). - On the browser: Zone.js monkey-patches globals in the customer's browser. Zalando "are not big fans of this" and opted out entirely (concepts/zone-js-monkey-patching).
Zalando's resolution¶
Opt out of context propagation on both client and server
and pass span objects manually through function parameters,
using OTel's third startup form
(tracer.startSpan("name", {}, context)). This is the
patterns/manual-span-passing-over-async-context pattern.
Trade-offs:
- Loss: spans must be threaded explicitly; libraries that want to create child spans must accept a context / parent- span parameter, making the API uglier.
- Gain (server): seamless migration from OpenTracing; no big-bang rewrite of the large existing instrumentation codebase.
- Gain (browser): no runtime monkey-patching of customer- browser globals; lower bundle size; no Zone.js surprise interactions with third-party JS.
Seen in¶
- sources/2024-07-28-zalando-opentelemetry-for-javascript-observability-at-zalando โ the canonical "why not" for OTel context propagation in both runtimes.