实体传播
状态: 开发中
概述
实体传播提供了一种通过环境变量在进程边界传递实体信息的方法。这允许实体在父进程和子进程之间共享,类似于分布式系统中跟踪上下文的传播方式。当外部进程比子进程自身能发现的更多地了解子实体时,这种方法尤其有用。
实体传播有益的常见场景包括:
- 容器编排系统,其中编排器了解容器元数据
- CI/CD 流水线,其中构建系统了解作业和环境详细信息
- 批处理系统,其中调度器了解任务上下文
- 具有特定实体上下文的命令行工具
环境变量提供了一种可靠的跨平台传播机制,因为它们会自动被子进程继承并在进程初始化期间可用。
通过环境变量指定实体信息
为了支持 OpenTelemetry 实现之间标准化的实体传播,本规范定义了 OTEL_ENTITIES 环境变量的格式和处理要求。
能够访问环境变量的 SDK 必须提供一个 EnvEntityDetector,它将使用 OTEL_ENTITIES 环境变量来发现实体并将已定义的实体与资源关联起来。
OTEL_ENTITIES 环境变量包含一个实体列表,采用一种紧凑的格式,旨在方便人类阅读和简洁表示。
格式规范
每个实体遵循此结构:
type{id_key1=id_value1,id_key2=id_value2}[desc_key1=desc_value1,desc_key2=desc_value2]@schema_url
其中
type是实体类型(必需,例如:“service”、“host”、“container”)。{...}包含作为逗号分隔的键值对的标识属性(必需,至少一个对)。[...]包含作为逗号分隔的键值对的描述性属性(可选)。@schema_url指定实体的 Schema URL(可选)。
多个实体由分号 (;) 分隔。
语法
entities := entity (";" entity)*
entity := type id_attrs desc_attrs? schema_url? | ""
type := [a-zA-Z][a-zA-Z0-9._-]*
id_attrs := "{" key_value_list "}"
desc_attrs := "[" key_value_list "]"
schema_url := "@" url_string
key_value_list := key_value ("," key_value)*
key_value := key "=" value
key := [a-zA-Z][a-zA-Z0-9._-]*
value := [^{}[\]@;,=]*
url_string := [^;]*
示例
# Single service entity
OTEL_ENTITIES="service{service.name=my-app,service.instance.id=instance-1}[service.version=1.0.0]"
# Multiple entities with schema URL
OTEL_ENTITIES="service{service.name=my-app,service.instance.id=instance-1}[service.version=1.0.0]@/schemas/1.21.0;host{host.id=host-123}[host.name=web-server-01]"
# Kubernetes pod entity
OTEL_ENTITIES="k8s.pod{k8s.pod.uid=pod-abc123}[k8s.pod.name=my-pod,k8s.pod.label.app=my-app]"
# Container with host (minimal descriptive attributes)
OTEL_ENTITIES="container{container.id=cont-456};host{host.id=host-789}[host.name=docker-host]"
# Minimal entity (only required fields)
OTEL_ENTITIES="service{service.name=minimal-app}"
# Empty strings are allowed (leading, trailing, and consecutive semicolons are ignored)
OTEL_ENTITIES=";service{service.name=app1};;host{host.id=host-123};"
解析算法
- 通过分号 (
;) 分割输入字符串以获取单个实体定义。 - 对于每个实体定义:a. 如果实体定义为空,则跳过(允许连续的分号以及前导/尾随分号)。b. 提取实体类型(
{之前的所有内容)。c. 从{...}块中提取标识属性。d. 从[...]块(如果存在)中提取描述性属性。e. 从@...部分(如果存在)中提取 schema URL。 - 使用逗号 (
,) 作为分隔符,使用等号 (=) 进行赋值来解析键值对列表。 - 验证每个实体是否具有非空类型和至少一个标识属性。
- 创建实体对象并将它们与资源关联。
字符编码
所有属性值都必须被视为字符串,并且 baggage-octet 范围之外的字符必须按照 W3C Baggage 规范进行百分比编码。
当保留字符 {}[]@;,= 出现在属性值中时,必须对其进行百分比编码。
{→%7B}→%7D[→%5B]→%5D@→%40;→%3B,→%2C=→%3D
示例
# Entity with reserved characters in attribute values
OTEL_ENTITIES="service{service.name=my%2Capp,service.instance.id=inst-1}[config=key%3Dvalue%5Bprod%5D]"
# Resolves to: service.name="my,app", config="key=value[prod]"
验证要求
- 实体类型不能为空,并且必须匹配模式
[a-zA-Z][a-zA-Z0-9._-]*。 {...}块中必须至少存在一个标识属性。- 属性键不能为空,并且应遵循 OpenTelemetry 语义约定。
- Schema URL(如果存在)必须是有效的 URI。
- 实体类型应遵循现有的 OpenTelemetry 实体命名约定(例如,“service”、“host”、“container”、“k8s.pod”)。
错误处理
SDK 应具备对格式错误输入的弹性,并遵循以下错误处理规则:
语法无效:如果环境变量包含无效语法,SDK 应记录警告并忽略格式错误的部分,同时处理有效的部分。
示例:
OTEL_ENTITIES="service{service.name=app1};invalid{syntax;service{service.name=app2}"会处理第一个有效的实体并跳过格式错误的部分。缺少必填字段:如果实体缺少必填字段(类型或标识属性),SDK 应记录警告并跳过该实体。
示例:
OTEL_ENTITIES="service{};host{host.id=123}"会跳过 service 实体(缺少标识属性)并处理 host 实体。重复实体:如果定义了多个具有相同标识属性的相同类型的实体,SDK 应使用最后一个出现,并应记录警告。
示例:
OTEL_ENTITIES="service{service.name=app1}[version=1.0];service{service.name=app1}[version=2.0]"使用version=2.0。Schema URL 验证:如果存在 Schema URL 但无效,SDK 应记录警告并忽略该 URL,同时处理该实体。
示例:
OTEL_ENTITIES="service{service.name=app1}@invalid-url"会处理该实体但忽略无效的 URL。冲突的标识属性:如果两个相同类型的实体为同一个标识属性键定义了不同的值,SDK 应记录警告并只保留最后一个实体。
示例:
OTEL_ENTITIES="service{service.name=app1};service{service.name=app2}"只创建 service.name=app2 实体。冲突的描述性属性:如果两个实体为同一个描述性属性键定义了不同的值,SDK 应使用最后一个实体定义的属性值,并应记录警告。冲突的属性不应被记录在最后一个实体之外的实体中。
示例:
OTEL_ENTITIES="service{service.name=app1}[version=1.0];service{service.name=app2}[version=2.0]"结果是 app1 服务没有 version 属性,app2 服务具有version=2.0。
EnvEntityDetector
待补充。