diff --git a/CHANGELOG.md b/CHANGELOG.md index a254eb0a637..fd09d96e1dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ release. ### Context +- Add response propagators. + ([#3825](https://github.com/open-telemetry/opentelemetry-specification/pull/3825)) + ### Traces ### Metrics diff --git a/internal/img/response-propagator-use-case.png b/internal/img/response-propagator-use-case.png new file mode 100644 index 00000000000..c22f89541f5 Binary files /dev/null and b/internal/img/response-propagator-use-case.png differ diff --git a/spec-compliance-matrix.md b/spec-compliance-matrix.md index 94bd625ceb1..af1c8eecbcc 100644 --- a/spec-compliance-matrix.md +++ b/spec-compliance-matrix.md @@ -254,6 +254,7 @@ Disclaimer: this list of features is still a work in progress, please refer to t | Get current Context | | N/A| + | + | + | + | + | + | + | + | + | + | | Composite Propagator | | + | + | + | + | + | + | + | + | + | + | + | | Global Propagator | | + | + | + | + | + | + | + | + | + | + | + | +| [ResponsePropagator](specification/context/api-propagators.md#response-propagator)| | - | - | - | - | - | - | - | - | - | - | - | | TraceContext Propagator | | + | + | + | + | + | + | + | + | + | + | + | | B3 Propagator | | + | + | + | + | + | + | + | + | + | + | + | | Jaeger Propagator | | + | + | + | + | + | + | | + | + | - | + | diff --git a/specification/configuration/file-configuration.md b/specification/configuration/file-configuration.md index 6e75166befc..1ba353b9b7c 100644 --- a/specification/configuration/file-configuration.md +++ b/specification/configuration/file-configuration.md @@ -297,6 +297,7 @@ Interpret [configuration model](#in-memory-configuration-model) and return SDK c * `MeterProvider` * `LoggerProvider` * `Propagators` +* `ResponsePropagators` The multiple responses MAY be returned using a tuple, or some other data structure encapsulating the components. diff --git a/specification/context/api-propagators.md b/specification/context/api-propagators.md index 762b309ef01..65cc1da3401 100644 --- a/specification/context/api-propagators.md +++ b/specification/context/api-propagators.md @@ -1,6 +1,6 @@ # Propagators API -**Status**: [Stable, Feature-Freeze](../document-status.md) +**Status**: [Mixed](../document-status.md)
Table of Contents @@ -8,6 +8,8 @@ - [Overview](#overview) +- [Propagator Categories](#propagator-categories) + * [Response Propagator](#response-propagator) - [Propagator Types](#propagator-types) * [Carrier](#carrier) * [Operations](#operations) @@ -28,9 +30,13 @@ * [Composite Extract](#composite-extract) * [Composite Inject](#composite-inject) - [Global Propagators](#global-propagators) + * [Response Propagators](#response-propagators) * [Get Global Propagator](#get-global-propagator) * [Set Global Propagator](#set-global-propagator) + * [Get Global ResponsePropagator](#get-global-responsepropagator) + * [Set Global ResponsePropagator](#set-global-responsepropagator) - [Propagators Distribution](#propagators-distribution) +- [Response Propagators Distribution](#response-propagators-distribution) * [B3 Requirements](#b3-requirements) + [B3 Extract](#b3-extract) + [B3 Inject](#b3-inject) @@ -58,8 +64,49 @@ interceptors and `Propagators`, where the interceptors detect incoming and outgo The Propagators API is expected to be leveraged by users writing instrumentation libraries. +## Propagator Categories + +**Status**: [Experimental](../document-status.md) + +There are two categories of propagators: + +* `Propagator`, or "forward propagator", which sends data forward to the next +process in the chain. +* `ResponsePropagator` (experimental), a specialization of `Propagator`, which +sends trace context back to the caller. + +The API is the same for both categories, but instrumentation libraries MUST NOT +call `ResponsePropagator`s to propagate the context to the next process, and MUST +NOT call `Propagator`s when propagating the context back to the caller. + +For historical reasons, whenever the term "Propagator" is used, a forward +propagator is implied. + +### Response Propagator + +**Status**: [Experimental](../document-status.md) + +While the classic context propagation was designed to carry values to the next +process in the chain of execution, there are cases where we want to send the +trace context back to the caller. For instance, when a client has made an +initial document request to a backend, the backend might have generated a trace +context. Once the client loads the document, it can record the timings and use +the same trace context it got from the initial document headers. This trace +context might be used as a link to/from a new trace, or might be directly reused +as the parent of new spans. + +![ResponsePropagator Use-Case](../../internal/img/response-propagator-use-case.png) + +The trace context obtained from response propagators are meant to be consumed +only by the caller and shouldn't be propagated further back. For example, on the +scenario where a service (A) makes a call to a service (B), which in turns makes +a call to (C), means that the context from the service (C) should be used by +(B), and (B) should not propagate the same context to (A). + ## Propagator Types +**Status**: [Stable](../document-status.md) + A `Propagator` type defines the restrictions imposed by a specific transport and is bound to a data type, in order to propagate in-band context data across process boundaries. @@ -72,6 +119,8 @@ A binary `Propagator` type will be added in the future (see [#437](https://githu ### Carrier +**Status**: [Stable](../document-status.md) + A carrier is the medium used by `Propagator`s to read values from and write values to. Each specific `Propagator` type defines its expected carrier type, such as a string map or a byte array. @@ -80,12 +129,16 @@ Carriers used at [Inject](#inject) are expected to be mutable. ### Operations +**Status**: [Stable](../document-status.md) + `Propagator`s MUST define `Inject` and `Extract` operations, in order to write values to and read values from carriers respectively. Each `Propagator` type MUST define the specific carrier type and MAY define additional parameters. #### Inject +**Status**: [Stable](../document-status.md) + Injects the value into a carrier. For example, into the headers of an HTTP request. Required arguments: @@ -96,6 +149,8 @@ Required arguments: #### Extract +**Status**: [Stable](../document-status.md) + Extracts the value from an incoming request. For example, from the headers of an HTTP request. If a value can not be parsed from the carrier, for a cross-cutting concern, @@ -113,6 +168,8 @@ containing the extracted value, which can be a `SpanContext`, ## TextMap Propagator +**Status**: [Stable](../document-status.md) + `TextMapPropagator` performs the injection and extraction of a cross-cutting concern value as string key/values pairs into carriers that travel in-band across process boundaries. @@ -132,6 +189,8 @@ avoid runtime allocations. ### Fields +**Status**: [Stable](../document-status.md) + The predefined propagation fields. If your carrier is reused, you should delete the fields here before calling [Inject](#inject). @@ -154,6 +213,8 @@ variable names. To get a full list of fields for a specific carrier object, use ### TextMap Inject +**Status**: [Stable](../document-status.md) + Injects the value into a carrier. The required arguments are the same as defined by the base [Inject](#inject) operation. @@ -164,6 +225,8 @@ Optional arguments: #### Setter argument +**Status**: [Stable](../document-status.md) + Setter is an argument in `Inject` that sets values into given fields. `Setter` allows a `TextMapPropagator` to set propagated fields into a carrier. @@ -172,6 +235,8 @@ One of the ways to implement it is `Setter` class with `Set` method as described ##### Set +**Status**: [Stable](../document-status.md) + Replaces a propagated field with the given value. Required arguments: @@ -184,6 +249,8 @@ The implementation SHOULD preserve casing (e.g. it should not transform `Content ### TextMap Extract +**Status**: [Stable](../document-status.md) + Extracts the value from an incoming request. The required arguments are the same as defined by the base [Extract](#extract) operation. @@ -196,6 +263,8 @@ Returns a new `Context` derived from the `Context` passed as argument. #### Getter argument +**Status**: [Stable](../document-status.md) + Getter is an argument in `Extract` that get value from given field `Getter` allows a `TextMapPropagator` to read propagated fields from a carrier. @@ -206,6 +275,8 @@ expose corresponding methods as delegates or other ways. ##### Keys +**Status**: [Stable](../document-status.md) + The `Keys` function MUST return the list of all the keys in the carrier. Required arguments: @@ -220,6 +291,8 @@ For example, it can be used to detect all keys following the `uberctx-{user-defi ##### Get +**Status**: [Stable](../document-status.md) + The Get function MUST return the first value of the given propagation key or return null if the key doesn't exist. Required arguments: @@ -231,6 +304,8 @@ The Get function is responsible for handling case sensitivity. If the getter is ## Injectors and Extractors as Separate Interfaces +**Status**: [Stable](../document-status.md) + Languages can choose to implement a `Propagator` type as a single object exposing `Inject` and `Extract` methods, or they can opt to divide the responsibilities further into individual `Injector`s and `Extractor`s. A @@ -239,6 +314,8 @@ responsibilities further into individual `Injector`s and `Extractor`s. A ## Composite Propagator +**Status**: [Stable](../document-status.md) + Implementations MUST offer a facility to group multiple `Propagator`s from different cross-cutting concerns in order to leverage them as a single entity. @@ -258,6 +335,8 @@ There MUST be functions to accomplish the following operations. ### Create a Composite Propagator +**Status**: [Stable](../document-status.md) + Required arguments: - A list of `Propagator`s or a list of `Injector`s and `Extractor`s. @@ -266,6 +345,8 @@ Returns a new composite `Propagator` with the specified `Propagator`s. ### Composite Extract +**Status**: [Stable](../document-status.md) + Required arguments: - A `Context`. @@ -277,6 +358,8 @@ If the `TextMapPropagator`'s `Extract` implementation accepts the optional `Gett ### Composite Inject +**Status**: [Stable](../document-status.md) + Required arguments: - A `Context`. @@ -288,11 +371,13 @@ If the `TextMapPropagator`'s `Inject` implementation accepts the optional `Sette ## Global Propagators +**Status**: [Stable](../document-status.md) + The OpenTelemetry API MUST provide a way to obtain a propagator for each supported `Propagator` type. Instrumentation libraries SHOULD call propagators -to extract and inject the context on all remote calls. Propagators, depending on -the language, MAY be set up using various dependency injection techniques or -available as global accessors. +to extract and inject the context on all outgoing remote calls. Propagators, +depending on the language, MAY be set up using various dependency injection +techniques or available as global accessors. **Note:** It is a discouraged practice, but certain instrumentation libraries might use proprietary context propagation protocols or be hardcoded to use a @@ -306,20 +391,37 @@ traces, metrics, logging and more. Therefore, context propagation MAY be enabled for any of them independently. For instance, a span exporter may be left unconfigured, although the trace context propagation was configured to enrich logs or metrics. -Platforms such as ASP.NET may pre-configure out-of-the-box +Instrumentation Libraries such as ASP.NET may pre-configure out-of-the-box propagators. If pre-configured, `Propagator`s SHOULD default to a composite `Propagator` containing the W3C Trace Context Propagator and the Baggage `Propagator` specified in the [Baggage API](../baggage/api.md#propagation). These platforms MUST also allow pre-configured propagators to be disabled or overridden. +### Response Propagators + +**Status**: [Experimental](../document-status.md) + +The OpenTelemetry API SHOULD provide similar facilities for `ResponsePropagator`s, +and instrumentation libraries SHOULD call response propagators to inject the +context on the response to remote calls. + +Instrumentation Libraries MUST NOT pre-configure `ResponsePropagator`s, those +should be explicitly enabled by service owners in order to not leak unintended +information to callers, which might be untrusted clients, like web browsers over +the public internet. + ### Get Global Propagator +**Status**: [Stable](../document-status.md) + This method MUST exist for each supported `Propagator` type. Returns a global `Propagator`. This usually will be composite instance. ### Set Global Propagator +**Status**: [Stable](../document-status.md) + This method MUST exist for each supported `Propagator` type. Sets the global `Propagator` instance. @@ -328,8 +430,30 @@ Required parameters: - A `Propagator`. This usually will be a composite instance. +### Get Global ResponsePropagator + +**Status**: [Experimental](../document-status.md) + +This method MUST exist for each supported `ResponsePropagator` type. + +Returns a global `ResponsePropagator`. This usually will be composite instance. + +### Set Global ResponsePropagator + +**Status**: [Experimental](../document-status.md) + +This method MUST exist for each supported `ResponsePropagator` type. + +Sets the global `ResponsePropagator` instance. + +Required parameters: + +- A `ResponsePropagator`. This usually will be a composite instance. + ## Propagators Distribution +**Status**: [Stable](../document-status.md) + The official list of propagators that MUST be maintained by the OpenTelemetry organization and MUST be distributed as OpenTelemetry extension packages: @@ -355,8 +479,17 @@ Additional `Propagator`s implementing vendor-specific protocols such as AWS X-Ray trace header protocol MUST NOT be maintained or distributed as part of the Core OpenTelemetry repositories. +## Response Propagators Distribution + +**Status**: [Experimental](../document-status.md) + +At the moment, no `ResponsePropagator`s are available. A candidate for the +near-future is W3C TraceContext's `traceresponse`. + ### B3 Requirements +**Status**: [Stable](../document-status.md) + B3 has both single and multi-header encodings. It also has semantics that do not map directly to OpenTelemetry such as a debug trace flag, and allowing spans from both sides of request to share the same id. To maximize compatibility @@ -365,6 +498,8 @@ been established for B3 context propagation. #### B3 Extract +**Status**: [Stable](../document-status.md) + When extracting B3, propagators: * MUST attempt to extract B3 encoded using single and multi-header @@ -377,6 +512,8 @@ When extracting B3, propagators: #### B3 Inject +**Status**: [Stable](../document-status.md) + When injecting B3, propagators: * MUST default to injecting B3 using the single-header format @@ -387,11 +524,15 @@ When injecting B3, propagators: #### Fields +**Status**: [Stable](../document-status.md) + Fields MUST return the header names that correspond to the configured format, i.e., the headers used for the inject operation. #### Configuration +**Status**: [Stable](../document-status.md) + | Option | Extract Order | Inject Format | Specification | |-----------|---------------|---------------| ------------------| | B3 Single | Single, Multi | Single | [Link][b3-single] | diff --git a/specification/overview.md b/specification/overview.md index c8e2a302db1..6bae8ea9e3c 100644 --- a/specification/overview.md +++ b/specification/overview.md @@ -343,13 +343,19 @@ See the [Context](context/README.md) ## Propagators -OpenTelemetry uses `Propagators` to serialize and deserialize cross-cutting concern values -such as `Span`s (usually only the `SpanContext` portion) and `Baggage`. Different `Propagator` types define the restrictions -imposed by a specific transport and bound to a data type. +OpenTelemetry uses `Propagators` to serialize and deserialize payloads for +cross-cutting applications, such as `SpanContext` and +`Baggage`. Various `Propagator` categories and types define the restrictions +imposed, and are specific according to direction, transport, and data-type binding. + +Propagators can be of one of two categories: `Propagator` (forward), or +`ResponsePropagator` (backward). See [Propagator +Categories](context/api-propagators.md#propagator-categories). The Propagators API currently defines one `Propagator` type: -- `TextMapPropagator` injects values into and extracts values from carriers as text. +- `TextMapPropagator` injects values into and extracts values from carriers as + text. ## Collector