Propagators API
状态: 稳定
概述
跨领域关注点通过 Propagator 将其状态发送到下一个进程,Propagator 定义为用于在应用程序交换的消息中读写上下文数据的对象。每个关注点都为每种支持的 Propagator 类型创建一组 Propagator。
Propagator 利用 Context 为每个跨领域关注点(例如 traces 和 Baggage)注入和提取数据。
传播通常通过库特定的请求拦截器和 Propagators 的协作来实现,其中拦截器检测传入和传出的请求,并分别使用 Propagator 的 extract 和 inject 操作。
Propagators API 预计将被编写仪器库的用户利用。
Propagator 类型
A Propagator type 定义了特定传输施加的限制,并与数据类型绑定,以便在进程边界上传播带内上下文数据。
Propagators API 目前定义了一个 Propagator 类型
TextMapPropagator是一种将值注入和从载体中提取为字符串键/值对的类型。
Carrier
Carrier 是 Propagator 用于读写值的媒介。每种特定的 Propagator 类型都定义了其预期的 Carrier 类型,例如字符串映射或字节数组。
在 Inject 中使用的 Carrier 应该是可变的。
操作
Propagator 必须定义 Inject 和 Extract 操作,以便分别将值写入载体和从载体读取值。每种 Propagator 类型必须定义特定的 Carrier 类型,并且可以定义附加参数。
Inject
将值注入载体。例如,注入到 HTTP 请求的标头中。
必需参数
- A
Context。Propagator 必须首先从Context中检索相应的值,例如SpanContext、Baggage或其他跨领域关注点的上下文。 - 持有传播字段的 Carrier。例如,传出消息或 HTTP 请求。
Extract
从传入请求中提取值。例如,从 HTTP 请求的标头中提取。
如果无法从 Carrier 解析出某个跨领域关注点的值,则实现不得抛出异常,也不得在 Context 中存储新值,以保留任何先前存在的有效值。
必需参数
- A
Context。 - 持有传播字段的 Carrier。例如,传入消息或 HTTP 请求。
返回一个从作为参数传递的 Context 派生的新 Context,其中包含提取的值,这可以是一个 SpanContext、Baggage 或其他跨领域关注点的上下文。
TextMap Propagator
TextMapPropagator 在进程边界上传播的载体中,将跨领域关注点的值作为字符串键/值对进行注入和提取。
客户端(注入器)和服务器(提取器)两侧的传播数据载体通常是 HTTP 请求。
为了提高兼容性,键/值对必须仅由构成有效 HTTP 标头字段的 US-ASCII 字符组成,如 RFC 9110 所述。
Getter 和 Setter 是用于提取和注入的可选辅助组件,它们被定义为与 Carrier 分开的对象,以避免运行时分配,通过消除对包装 Carrier 以访问其内容的附加接口实现对象的需要。
Getter 和 Setter 必须是无状态的,并且可以保存为常量,以便有效地避免运行时分配。
Fields
预定义的传播字段。如果您的 Carrier 被重用,则在调用 Inject 之前应删除此处字段。
Fields 被定义为标识 Carrier 中特定格式组件的字符串键。
例如,如果 Carrier 是一个一次性或不可变的请求对象,则无需清除字段,因为它们之前可能未被设置。如果它是一个可变的、可重试的对象,连续的调用应首先清除这些字段。
这方面的用例是
- 允许预分配字段,尤其是在 gRPC Metadata 等系统中
- 允许单次遍历迭代器
返回将被 TextMapPropagator 使用的字段列表。
请注意,某些 Propagator 除了返回的值外,可能还定义了具有可变名称的附加字段。要获取特定 Carrier 对象的完整字段列表,请使用 Keys 操作。
TextMap Inject
将值注入载体。必需参数与基础 Inject 操作定义的相同。
可选参数
- A
Setter用于设置传播键/值对。Propagators 可以多次调用它来设置多个对。这是一个语言可以自由定义的附加参数,以帮助将数据注入 Carrier。
Setter 参数
Setter 是 Inject 中的一个参数,用于将值设置到给定字段。
Setter 允许 TextMapPropagator 将传播的字段设置到 Carrier 中。
实现它的方法之一是 Setter 类,其中包含下面描述的 Set 方法。
Set
用给定值替换传播的字段。
必需参数
- 持有传播字段的 Carrier。例如,传出消息或 HTTP 请求。
- 字段的键。
- 字段的值。
如果使用的协议不区分大小写,则实现应保留大小写(例如,不应将 Content-Type 转换为 content-type),否则必须保留大小写。
TextMap Extract
从传入请求中提取值。必需参数与基础 Extract 操作定义的相同。
可选参数
- A
Getter用于获取每个传播键。这是一个语言可以自由定义的附加参数,以帮助从 Carrier 中提取数据。
返回一个从作为参数传递的 Context 派生的新 Context。
Getter 参数
Getter 是 Extract 中的一个参数,用于从给定字段获取值。
Getter 允许 TextMapPropagator 从 Carrier 中读取传播的字段。
实现它的方法之一是 Getter 类,其中包含下面描述的 Get、Keys 和 GetAll 方法。语言可以决定其他实现并公开相应的委托或其他方法。
Keys
Keys 函数必须返回 Carrier 中的所有键的列表。
必需参数
- 传播字段的 Carrier,例如 HTTP 请求。
Keys 函数可以被使用可变键名的 Propagator 调用,以遍历指定 Carrier 中的所有键。
例如,它可用于检测所有遵循 uberctx-{user-defined-key} 模式的键,如 Jaeger Propagation Format 所定义。
Get
Get 函数必须返回给定传播键的第一个值,或者在键不存在时返回 null。
必需参数
- 传播字段的 Carrier,例如 HTTP 请求。
- 字段的键。
Get 函数负责处理大小写敏感性。如果 getter 旨在与 HTTP 请求对象一起使用,则 getter 必须不区分大小写。
GetAll
对于许多语言实现,GetAll 函数将在 Getter 稳定发布后添加。对于这些语言,要求实现 Getter 包含 GetAll 会构成破坏性更改,因为先前有效的仪器将失败。语言实现应注意这一点,并以保持向后兼容的方式添加 GetAll。例如,通过提供基于 Get 的默认 GetAll 实现,或通过创建扩展的 Getter 类型。
如果显式实现,GetAll 函数必须返回给定传播键的所有值。它应按它们在 Carrier 中出现的顺序返回。如果键不存在,它应返回一个空集合。
必需参数
- 传播字段的 Carrier,例如 HTTP 请求。
- 字段的键。
GetAll 函数负责处理大小写敏感性。如果 getter 旨在与 HTTP 请求对象一起使用,则 getter 必须不区分大小写。
Injectors 和 Extractors 作为独立接口
语言可以选择将 Propagator 类型实现为一个公开 Inject 和 Extract 方法的单个对象,或者它们可以选择将职责进一步划分为单独的 Injector 和 Extractor。Propagator 可以通过组合单独的 Injector 和 Extractor 来实现。
Composite Propagator
实现必须提供一个机制来组合来自不同跨领域关注点的多个 Propagator,以便将它们作为一个实体利用。
一个复合 propagator 可以由一组 propagators 或一组 injectors 和 extractors 构建。生成的复合 Propagator 将按照指定的顺序调用 Propagator、Injector 或 Extractor。
每个复合 Propagator 将实现特定的 Propagator 类型,例如 TextMapPropagator,因为不同的 Propagator 类型可能会操作不同的数据类型。
必须提供以下操作的函数。
- 创建复合 propagator
- 从复合 propagator 中提取
- 注入到复合 propagator 中
创建 Composite Propagator
必需参数
- A list of
Propagators or a list ofInjectors andExtractors.
返回一个具有指定 Propagators 的新复合 Propagator。
Composite Extract
必需参数
- A
Context。 - 持有传播字段的 Carrier。
如果 TextMapPropagator 的 Extract 实现接受可选的 Getter 参数,则以下参数是必需的,否则它们是可选的
- 用于获取每个传播键的
Getter实例。
Composite Inject
必需参数
- A
Context。 - 持有传播字段的 Carrier。
如果 TextMapPropagator 的 Inject 实现接受可选的 Setter 参数,则以下参数是必需的,否则它们是可选的
- 用于设置传播键/值对的
Setter。Propagators 可以多次调用它来设置多个对。
全局 Propagators
OpenTelemetry API 必须提供一种方法来获取每种受支持的 Propagator 类型的 propagator。仪器库应调用 propagators 来提取和注入所有远程调用的上下文。Propagators,取决于语言,可以通过各种依赖注入技术进行设置,或作为全局访问器提供。
注意: 这是一个不推荐的做法,但某些仪器库可能会使用专有的上下文传播协议或被硬编码使用特定的协议。在这种情况下,仪器库可以选择不使用 API 提供的 propagators,而是硬编码上下文提取和注入逻辑。
OpenTelemetry API 必须使用 no-op propagators,除非明确配置。上下文传播可能用于各种遥测信号 - traces、metrics、logging 等。因此,上下文传播可以独立地为其中任何一个启用。例如,span exporter 可能未配置,尽管 trace context propagation 已配置为丰富日志或指标。
ASP.NET 等平台可能提供开箱即用的预配置 propagators。如果预配置,Propagator 应该默认为一个复合 Propagator,其中包含 W3C Trace Context Propagator 和 Baggage API 中指定的 Baggage Propagator。这些平台还必须允许禁用或覆盖预配置的 propagators。
Get Global Propagator
此方法必须存在于每种受支持的 Propagator 类型。
返回一个全局 Propagator。这通常会是一个复合实例。
Set Global Propagator
此方法必须存在于每种受支持的 Propagator 类型。
设置全局 Propagator 实例。
必需参数
- A
Propagator。这通常会是一个复合实例。
Propagators 分发
必须由 OpenTelemetry 组织维护的 propagator 的官方列表,并且必须作为 OpenTelemetry 扩展包分发
- W3C TraceContext。也可以作为 OpenTelemetry API 的一部分进行分发。
- W3C Baggage。也可以作为 OpenTelemetry API 的一部分进行分发。
- B3.
- Jaeger.
这是一个附加 propagators 的列表,可以作为 OpenTelemetry 扩展包维护和分发
- OT Trace。OpenTracing Basic Tracers 使用的传播格式。它不得在最终的 propagator 名称中使用
OpenTracing,因为它在 OpenTracing 生态系统中不是广泛采用的格式。 - OpenCensus BinaryFormat。OpenCensus 使用的传播格式,描述了如何将 span context 格式化为二进制格式,并且不指定键。它通常与 OpenCensus gRPC 一起使用,使用
grpc-trace-bin传播键。
实现 AWS X-Ray 跟踪标头协议等供应商特定协议的附加 Propagator 不得作为核心 OpenTelemetry 存储库的一部分进行维护或分发。
W3C Trace Context 要求
W3C Trace Context propagator 必须按照 W3C Trace Context Level 2 中的规定解析和验证 traceparent 和 tracestate HTTP 标头。W3C Trace Context propagator 必须使用相同的标头传播有效的 traceparent 值。W3C Trace Context propagator 必须传播有效的 tracestate,除非该值为"",在这种情况下可以省略 tracestate 标头。
在将 trace context 注入或从载体中提取时,将传播 SpanContext 中的以下字段。
- TraceID (16 字节)
- SpanID (8 字节)
- TraceFlags (8 位)
- TraceState (字符串,除非为空)
B3 要求
B3 具有单标头和多标头编码。它还具有不能直接映射到 OpenTelemetry 的语义,例如 debug trace flag,并且允许请求双方的 span 共享相同的 ID。为了最大化 OpenTelemetry 和 Zipkin 实现之间的兼容性,已为 B3 context propagation 建立以下指南。
B3 Extract
提取 B3 时,propagators
- 必须尝试提取使用单标头和多标头格式编码的 B3。单标头变体优先于多标头版本。
- 必须保留接收到的 debug trace flag,并将其传播到后续请求。此外,当设置了 debug flag 时,OpenTelemetry 实现必须设置 sampled trace flag。
- 不得将
X-B3-SpanId重用为服务器端 span 的 ID。
B3 Inject
注入 B3 时,propagators
- 必须默认为使用单标头格式注入 B3
- 必须提供配置以将默认注入格式更改为 B3 多标头
- 不得传播
X-B3-ParentSpanId,因为 OpenTelemetry 不支持将同一 ID 重用于请求双方。
Fields
Fields 必须返回与配置格式对应的标头名称,即用于 inject 操作的标头。
配置
| Option | Extract Order | Inject Format | 规范 |
|---|---|---|---|
| B3 Single | Single, Multi | Single | Link |
| B3 Multi | Single, Multi | Multi | Link |