实体传播

状态: 开发中

概述

实体传播提供了一种通过环境变量在进程边界传递实体信息的方法。这允许实体在父进程和子进程之间共享,类似于分布式系统中跟踪上下文的传播方式。当外部进程比子进程自身能发现的更多地了解子实体时,这种方法尤其有用。

实体传播有益的常见场景包括:

  • 容器编排系统,其中编排器了解容器元数据
  • 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};"

解析算法

  1. 通过分号 (;) 分割输入字符串以获取单个实体定义。
  2. 对于每个实体定义:a. 如果实体定义为空,则跳过(允许连续的分号以及前导/尾随分号)。b. 提取实体类型({ 之前的所有内容)。c. 从 {...} 块中提取标识属性。d. 从 [...] 块(如果存在)中提取描述性属性。e. 从 @... 部分(如果存在)中提取 schema URL。
  3. 使用逗号 (,) 作为分隔符,使用等号 (=) 进行赋值来解析键值对列表。
  4. 验证每个实体是否具有非空类型和至少一个标识属性。
  5. 创建实体对象并将它们与资源关联。

字符编码

所有属性值都必须被视为字符串,并且 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 应具备对格式错误输入的弹性,并遵循以下错误处理规则:

  1. 语法无效:如果环境变量包含无效语法,SDK 应记录警告并忽略格式错误的部分,同时处理有效的部分。

    示例:OTEL_ENTITIES="service{service.name=app1};invalid{syntax;service{service.name=app2}" 会处理第一个有效的实体并跳过格式错误的部分。

  2. 缺少必填字段:如果实体缺少必填字段(类型或标识属性),SDK 应记录警告并跳过该实体。

    示例:OTEL_ENTITIES="service{};host{host.id=123}" 会跳过 service 实体(缺少标识属性)并处理 host 实体。

  3. 重复实体:如果定义了多个具有相同标识属性的相同类型的实体,SDK 应使用最后一个出现,并应记录警告。

    示例:OTEL_ENTITIES="service{service.name=app1}[version=1.0];service{service.name=app1}[version=2.0]" 使用 version=2.0

  4. Schema URL 验证:如果存在 Schema URL 但无效,SDK 应记录警告并忽略该 URL,同时处理该实体。

    示例:OTEL_ENTITIES="service{service.name=app1}@invalid-url" 会处理该实体但忽略无效的 URL。

  5. 冲突的标识属性:如果两个相同类型的实体为同一个标识属性键定义了不同的值,SDK 应记录警告并只保留最后一个实体。

    示例:OTEL_ENTITIES="service{service.name=app1};service{service.name=app2}" 只创建 service.name=app2 实体。

  6. 冲突的描述性属性:如果两个实体为同一个描述性属性键定义了不同的值,SDK 应使用最后一个实体定义的属性值,并应记录警告。冲突的属性不应被记录在最后一个实体之外的实体中。

    示例:OTEL_ENTITIES="service{service.name=app1}[version=1.0];service{service.name=app2}[version=2.0]" 结果是 app1 服务没有 version 属性,app2 服务具有 version=2.0

EnvEntityDetector

待补充。