实体数据模型
状态: 开发中
实体代表与生成的遥测数据(跟踪、指标、剖面、日志)相关的一个感兴趣的对象。
例如,使用 OpenTelemetry SDK 生成的遥测数据通常与一个 service 实体相关联。同样,OpenTelemetry 为 host 定义了系统指标。在这种情况下,host 是我们希望将指标与之相关联的实体。
实体也可能与生成的遥测数据间接关联。例如,一个生成遥测数据的服务也与运行该服务的进程相关联,因此我们说 service 实体与 process 实体相关联。进程通常也在主机上运行,因此我们说 process 实体与 host 实体相关联。
实体关系建模将在未来的规范工作中进行完善。
下面的数据模型定义了一个实体的逻辑模型(与实体数据如何记录的物理格式和编码无关)。
| 字段 | 类型 | 描述 |
|---|---|---|
| 类型 | 字符串 | 定义实体的类型。在实体的生命周期中 MUST 不得更改。例如:“service”或“host”。此字段是必需的,对于有效实体 MUST 不能为空。 |
| Id | map<string, attribute value> | 标识实体的属性。 在实体的生命周期中 MUST 不得更改。Id 必须至少包含一个属性。 |
| 描述 | map<string, attribute value> | 实体的描述性(非标识性)属性。 在实体的生命周期中 MAY 更改。MAY 为空。这些属性不是实体身份的一部分。 |
最小有效标识
通常,遥测生产者可以方便地从一个实体的许多可用属性中组合出一个 Id。在所有可用属性中,实体 Id 应包含足以唯一标识该实体的最小属性集。例如,主机上的进程可以通过 (process.pid,process.start_time) 属性唯一标识。添加例如 process.executable.name 属性到 Id 是不必要的,并且违反了最小有效标识规则。
可重复标识
实体的标识属性 SHOULD 是观察者可重复获取的值。例如,无论身份是来自进程本身(例如通过 SDK)、运行在同一主机上的 OpenTelemetry Collector,还是描述该进程的任何其他系统生成的,process 实体 SHOULD 具有相同的身份(并被识别为同一进程)。
有许多方法可以跨多个观察者实现可重复的标识属性。虽然许多成功的系统依赖于从中央注册表或知识库推送身份,但 OpenTelemetry 必须支持所有可能的场景。
标识属性
OpenTelemetry 语义约定 MUST 为每个定义的实体类型定义一组标识属性键。
标识属性的名称 SHOULD 使用实体类型作为前缀,以避免与其他实体类型冲突。例如,k8s.node 实体使用 k8s.node.uid 作为标识属性。
当一个实体可以由多个观察者发出时,适用以下规则:
两个独立的观察者,如果报告同一个实体,则必须能够为所有标识属性提供相同的值。
如果一个观察者无法可靠地获取一个或多个标识属性,它 MUST 不使用该实体类型发出遥测数据。相反,它 SHOULD
- 委托给能够提供完整集合的观察者,并将该观察者视为“真相来源”(source of truth),或者
- 发出一个“不同”的实体类型,并带有它能够可靠填充的标识属性集。
这确保了实体身份在观察者之间是一致且无歧义的。
资源和实体
OpenTelemetry 信号(指标、日志、跟踪和剖面)支持附加一个或多个实体,每个实体代表一个特定的基础设施或运行时组件,例如 k8s.cluster、k8s.node、host 或 container。
以前,Resource 数据模型依赖于每个信号的扁平化属性。有了实体,遥测数据可以表示同一信号内的多个不同但相关的组件,每个组件都有自己的身份和额外元数据。实体利用与 Resource 模型相同的属性池。这使得数据编码和传输更加高效,并且与现有的 Resource 属性向后兼容。
属性引用模型
实体可以在遥测信号的 resource 部分中定义。它们的标识和描述性属性引用在 Resource 中定义的共享属性。例如,在 OTLP 中,实体不直接携带自己的键值对。相反,它们引用 resource.attributes 中的键,以保持与 OTLP 1.x 的向后兼容性。
这种方法旨在支持属性扁平化,即属性不与特定结构绑定,而是可以在不同实体之间灵活引用。该模型提供了:
- 一种通过共享属性标识和描述实体的方式。
- 避免数据重复和不一致的能力。
- 一种更高效的编码和传输表示。
共享描述属性的放置
属性扁平化允许多个实体引用相同的属性键,但在不同实体中具有不同的值。在这种情况下,适用以下规则:
如果多个实体共享相同的描述性属性键,并且值可能冲突,则该属性 MUST 逻辑上仅属于**其中一个**实体。所有其他实体 SHOULD 不引用它。该属性 MUST 由**最具体**的实体引用,即在拓扑图中离与遥测信号相关联的实体最近的那个。
示例
如果一个信号同时包含 k8s.cluster 和 k8s.node 实体,并且具有 cloud.availability_zone 描述性属性,该属性可能具有不同的值,那么**只有** k8s.node 实体可以引用此键——因为它是一个更具体的实体。
其他实体(例如 k8s.cluster)可以在单独的遥测通道(例如实体事件)中报告此属性,其中已知完整的归属上下文。
实体示例
本节非规范性,仅用于演示数据模型。
以下是实体示例,它们典型的标识属性以及可能与该实体相关联的一些描述性属性示例。
注意:这些示例 MAY 与语义约定有所不同。
| 实体 | 实体类型 | 标识属性 | 描述性属性 |
| Container | container | container.id | container.image.id container.image.name container.image.tag.{key} container.label.{key} container.name container.runtime oci.manifest.digest container.command |
| Host | host | host.id | host.arch host.name host.type host.image.id host.image.name host.image.version host.type |
| Kubernetes 节点 | k8s.node | k8s.node.uid | k8s.node.name |
| Kubernetes Pod | k8s.pod | k8s.pod.uid | k8s.pod.name k8s.pod.label.{key} k8s.pod.annotation.{key} |
| 服务实例 | service.instance | service.instance.id service.name service.namesapce | service.version |