From b8948d9cec3994e396898feca7a10025d08370db Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Mon, 20 Jul 2020 14:53:18 +0200 Subject: [PATCH] Small clean up for Propagators. (#577) --- CHANGELOG.md | 1 + specification/context/api-propagators.md | 155 +++++++++++++++-------- specification/overview.md | 9 +- specification/trace/api.md | 3 +- 4 files changed, 111 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9bf2df7165..f20a279fa42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Updates: - Add semantic convention for NGINX custom HTTP 499 status code. - Adapt semantic conventions for the span name of messaging systems ([#690](https://github.com/open-telemetry/opentelemetry-specification/pull/690)) - Specify how `Probability` sampler is used with `ParentOrElse` sampler. +- Clean up api-propagators.md, by extending documentation and removing redundant sections ([#577](https://github.com/open-telemetry/opentelemetry-specification/pull/577)) ## v0.6.0 (07-01-2020) diff --git a/specification/context/api-propagators.md b/specification/context/api-propagators.md index d5dae81ff17..627517208dd 100644 --- a/specification/context/api-propagators.md +++ b/specification/context/api-propagators.md @@ -6,12 +6,17 @@ Table of Contents - [Overview](#overview) -- [HTTP Text Format](#http-text-format) +- [Propagator Types](#propagator-types) + - [Carrier](#carrier) + - [Operations](#operations) + - [Inject](#inject) + - [Extract](#extract) +- [HTTPText Propagator](#httptext-propagator) - [Fields](#fields) - - [Inject](#inject) + - [Inject](#inject-1) - [Setter argument](#setter) - [Set](#set) - - [Extract](#extract) + - [Extract](#extract-1) - [Getter argument](#getter) - [Get](#get) - [Composite Propagator](#composite-propagator) @@ -24,41 +29,94 @@ Table of Contents Cross-cutting concerns send their state to the next process using `Propagator`s, which are defined as objects used to read and write context data to and from messages exchanged by the applications. -Each concern creates a set of `Propagator`s for every supported `Format`. +Each concern creates a set of `Propagator`s for every supported +`Propagator` type. -Propagators leverage the `Context` to inject and extract data for each +`Propagator`s leverage the `Context` to inject and extract data for each cross-cutting concern, such as traces and correlation context. +Propagation is usually implemented via a cooperation of library-specific request +interceptors and `Propagators`, where the interceptors detect incoming and outgoing requests and use the `Propagator`'s extract and inject operations respectively. + The Propagators API is expected to be leveraged by users writing instrumentation libraries. -The Propagators API currently consists of one `Format`: +## Propagator Types + +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. + +The Propagators API currently defines one `Propagator` type: + +- `HTTPTextPropagator` is a type that inject values into and extracts values + from carriers as string key/value pairs. + +A binary `Propagator` type will be added in the future (see [#437](https://github.com/open-telemetry/opentelemetry-specification/issues/437)). + +### Carrier -- `HTTPTextFormat` is used to inject values into and extract values from carriers as text that travel - in-band across process boundaries. +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. -A binary `Format` will be added in the future. +Carriers used at [Inject](#inject) are expected to be mutable. -## HTTP Text Format +### Operations + +`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 CAN define additional parameters. + +#### Inject + +Injects the value into a carrier. For example, into the headers of an HTTP request. + +Required arguments: -`HTTPTextFormat` is a formatter that injects and extracts a cross-cutting concern -value as text into carriers that travel in-band across process boundaries. +- A `Context`. The Propagator MUST retrieve the appropriate value from the `Context` first, such as +`SpanContext`, `CorrelationContext` or another cross-cutting concern context. +- The carrier that holds the propagation fields. For example, an outgoing message or HTTP request. -Encoding is expected to conform to the HTTP Header Field semantics. Values are often encoded as -RPC/HTTP request headers. +#### Extract + +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, +the implementation MUST NOT throw an exception and MUST NOT store a new value in the `Context`, +in order to preserve any previously existing valid value. + +Required arguments: + +- A `Context`. +- The carrier that holds the propagation fields. For example, an incoming message or http response. + +Returns a new `Context` derived from the `Context` passed as argument, +containing the extracted value, which can be a `SpanContext`, +`CorrelationContext` or another cross-cutting concern context. + +## HTTPText Propagator + +`HTTPTextPropagator` 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. The carrier of propagated data on both the client (injector) and server (extractor) side is -usually an http request. Propagation is usually implemented via library-specific request -interceptors, where the client-side injects values and the server-side extracts them. +usually an HTTP request. + +`Getter` and `Setter` are optional helper components used for extraction and injection respectively, +and are defined as separate objects from the carrier to avoid runtime allocations, +by removing the need for additional interface-implementing-objects wrapping the carrier in order +to access its contents. -`HTTPTextFormat` MUST expose the APIs that injects values into carriers, -and extracts values from carriers. +`Getter` and `Setter` MUST be stateless and allowed to be saved as constants, in order to effectively +avoid runtime allocations. ### Fields The propagation fields defined. If your carrier is reused, you should delete the fields here before calling [inject](#inject). +Fields are defined as string keys identifying format-specific components in a carrier. + For example, if the carrier is a single-use or immutable request object, you don't need to clear fields as they couldn't have been set before. If it is a mutable, retryable object, successive calls should clear these fields first. @@ -68,25 +126,25 @@ The use cases of this are: - allow pre-allocation of fields, especially in systems like gRPC Metadata - allow a single-pass over an iterator -Returns list of fields that will be used by this formatter. +Returns list of fields that will be used by the `HttpTextPropagator`. ### Inject -Injects the value downstream. For example, as http headers. +Injects the value into a carrier. The required arguments are the same as defined by +the base [Inject](#inject) operation. -Required arguments: +Optional arguments: -- A `Context`. The Propagator MUST retrieve the appropriate value from the `Context` first, such as `SpanContext`, `CorrelationContext` or another cross-cutting concern context. For languages supporting current `Context` state, this argument is OPTIONAL, defaulting to the current `Context` instance. -- the carrier that holds propagation fields. For example, an outgoing message or http request. -- the `Setter` invoked for each propagation key to add or remove. +- A `Setter` invoked for each propagation key to add or remove. This is an additional + argument that languages are free to define to help inject data into the carrier. #### Setter argument -Setter is an argument in `Inject` that sets value into given field. +Setter is an argument in `Inject` that sets values into given fields. -`Setter` allows a `HTTPTextFormat` to set propagated fields into a carrier. +`Setter` allows a `HttpTextPropagator` to set propagated fields into a carrier. -`Setter` MUST be stateless and allowed to be saved as a constant to avoid runtime allocations. One of the ways to implement it is `Setter` class with `Set` method as described below. +One of the ways to implement it is `Setter` class with `Set` method as described below. ##### Set @@ -94,39 +152,31 @@ Replaces a propagated field with the given value. Required arguments: -- the carrier holds propagation fields. For example, an outgoing message or http request. +- the carrier holding the propagation fields. For example, an outgoing message or an HTTP request. - the key of the field. - the value of the field. -The implemenation SHOULD preserve casing (e.g. it should not transform `Content-Type` to `content-type`) if the used protocol is case insensitive, otherwise it MUST preserve casing. +The implementation SHOULD preserve casing (e.g. it should not transform `Content-Type` to `content-type`) if the used protocol is case insensitive, otherwise it MUST preserve casing. ### Extract -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, -the implementation MUST NOT throw an exception and MUST NOT store a new value in the `Context`, -in order to preserve any previously existing valid value. - -Required arguments: +Extracts the value from an incoming request. The required arguments are the same as defined by +the base [Extract](#extract) operation. -- A `Context`. For languages supporting current `Context` state this argument is OPTIONAL, defaulting to the current `Context` instance. -- the carrier holds propagation fields. For example, an outgoing message or http request. -- the instance of `Getter` invoked for each propagation key to get. +Optional arguments: -Returns a new `Context` derived from the `Context` passed as argument, -containing the extracted value, which can be a `SpanContext`, -`CorrelationContext` or another cross-cutting concern context. +- A `Getter` invoked for each propagation key to get. This is an additional + argument that languages are free to define to help extract data from the carrier. -If the extracted value is a `SpanContext`, its `IsRemote` property MUST be set to true. +Returns a new `Context` derived from the `Context` passed as argument. #### Getter argument Getter is an argument in `Extract` that get value from given field -`Getter` allows a `HttpTextFormat` to read propagated fields from a carrier. +`Getter` allows a `HttpTextPropagator` to read propagated fields from a carrier. -`Getter` MUST be stateless and allowed to be saved as a constant to avoid runtime allocations. One of the ways to implement it is `Getter` class with `Get` method as described below. +One of the ways to implement it is `Getter` class with `Get` method as described below. ##### Get @@ -137,11 +187,11 @@ Required arguments: - the carrier of propagation fields, such as an HTTP request. - the key of the field. -The Get function is responsible for handling case sensitivity. If the getter is intended to work with a HTTP request object, the getter MUST be case insensitive. To improve compatibility with other text-based protocols, text `Format` implementions MUST ensure to always use the canonical casing for their attributes. NOTE: Canonical casing for HTTP headers is usually title case (e.g. `Content-Type` instead of `content-type`). +The Get function is responsible for handling case sensitivity. If the getter is intended to work with a HTTP request object, the getter MUST be case insensitive. ## Injectors and Extractors as Separate Interfaces -Languages can choose to implement a `Propagator` for a format as a single object +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 `Propagator` can be implemented by composing individual `Injector`s and @@ -156,9 +206,10 @@ single entity. A composite propagator can be built from a list of propagators, or a list of injectors and extractors. The resulting composite `Propagator` will invoke the `Propagator`s, `Injector`s, or `Extractor`s, in the order they were specified. -Each composite `Propagator` will be bound to a specific `Format`, such -as `HttpTextFormat`, as different `Format`s will likely operate on different +Each composite `Propagator` will implement a specific `Propagator` type, such +as `HttpTextPropagator`, as different `Propagator` types will likely operate on different data types. + There MUST be functions to accomplish the following operations. - Create a composite propagator @@ -192,7 +243,7 @@ Required arguments: ## Global Propagators Implementations MAY provide global `Propagator`s for -each supported `Format`. +each supported `Propagator` type. If offered, the global `Propagator`s should default to a composite `Propagator` containing the W3C Trace Context Propagator and the Correlation Context `Propagator` @@ -202,13 +253,13 @@ OpenTelemetry implementations. ### Get Global Propagator -This method MUST exist for each supported `Format`. +This method MUST exist for each supported `Propagator` type. Returns a global `Propagator`. This usually will be composite instance. ### Set Global Propagator -This method MUST exist for each supported `Format`. +This method MUST exist for each supported `Propagator` type. Sets the global `Propagator` instance. diff --git a/specification/overview.md b/specification/overview.md index 7f96cb69150..2c2d0fe918d 100644 --- a/specification/overview.md +++ b/specification/overview.md @@ -238,11 +238,12 @@ See the [Context](context/context.md) ## Propagators OpenTelemetry uses `Propagators` to serialize and deserialize cross-cutting concern values -such as `SpanContext` and `CorrelationContext` into a `Format`. Currently there is one -type of propagator: +such as `SpanContext` and `CorrelationContext`. Different `Propagator` types define the restrictions +imposed by a specific transport and bound to a data type. -- `HTTPTextFormat` which is used to inject and extract a value as text into carriers that travel - in-band across process boundaries. +The Propagators API currently defines one `Propagator` type: + +- `HTTPTextPropagator` injects values into and extracts values from carriers as text. ## Collector diff --git a/specification/trace/api.md b/specification/trace/api.md index 15280db3a9f..8afe289b8b5 100644 --- a/specification/trace/api.md +++ b/specification/trace/api.md @@ -180,7 +180,8 @@ TraceID and a non-zero SpanID. `IsRemote` is a boolean flag which returns true if the SpanContext was propagated from a remote parent. -When creating children from remote spans, their IsRemote flag MUST be set to false. +When extracting a `SpanContext` through the Propagators API, its `IsRemote` flag MUST +be set to true, whereas the SpanContext of any child spans MUST have it set to false. Please review the W3C specification for details on the [Tracestate field](https://www.w3.org/TR/trace-context/#tracestate-field).