2. OpenTelemetry 核心概念:信号、跨度、链路、上下文、资源与插桩

在深入值班机器人的链路追踪与告警聚合设计之前,必须建立对 OpenTelemetry 核心数据模型的统一认知。这六个概念构成了可观测性数据的骨架,理解它们之间的层次关系是后续实现分布式追踪、指标采集和日志关联的基础。

2.1 六大核心概念总览

OpenTelemetry 将可观测性数据抽象为 Signal(信号),而每个信号的具体承载单元则通过 Span(跨度)、Trace(链路)、Context(上下文)、Resource(资源) 和 Instrumentation(插桩) 来定义和传递。下表从定义、作用与典型场景三个维度进行对比:

概念 定义 核心作用 值班机器人场景示例
Signal(信号) 可观测性数据的三大类别:Traces、Metrics、Logs 区分数据类型,决定采集与处理方式 告警触发时同时产生 Trace 和 Metric 信号
Span(跨度) 一次操作的最小记录单元,包含名称、时间、属性、状态 记录单个操作的耗时与元数据 “查询告警规则”是一个 Span
Trace(链路) 由多个 Span 组成的树状结构,代表一次完整请求 串联跨服务的调用路径 从“接收告警”到“发送通知”的完整流程
Context(上下文) 携带 Trace ID、Span ID 等传播信息的对象 跨进程传递追踪状态 HTTP 头中传递 traceparent
Resource(资源) 描述产生数据的实体属性(服务名、版本、主机) 标识数据来源,支持多维过滤 service.name="值班机器人", host.id="node-01"
Instrumentation(插桩) 自动或手动在代码中嵌入观测代码的机制 降低接入成本,标准化数据采集 通过装饰器自动追踪每个 API 端点

2.2 Signal(信号)—— 可观测性的三大支柱

OpenTelemetry 将可观测性数据统一为三种信号类型,值班机器人在运行时需要同时处理这三种信号才能实现完整的告警聚合分析:

  • Traces(链路):记录请求在分布式系统中的完整路径,用于定位故障点。
  • Metrics(指标):聚合后的数值数据,如告警延迟 P99、通知成功率。
  • Logs(日志):带时间戳的文本记录,用于补充链路和指标的细节。
设计要点: 在值班机器人中,告警聚合阶段应优先使用 Trace 关联所有相关 Span,再通过 Span 的 Attributes 关联对应的 Metrics 和 Logs,避免三种信号各自独立导致数据孤岛。

2.3 Span(跨度)与 Trace(链路)

Span 是链路追踪的最小工作单元,而 Trace 是由多个 Span 组成的树状结构。每个 Span 必须包含以下关键字段:

字段 说明 值班机器人示例值
Span ID 16 字节唯一标识 a1b2c3d4e5f6g7h8
Trace ID 32 字节全局唯一标识 0af7651916cd43dd8448eb211c80319c
Parent Span ID 父 Span 的 ID,根 Span 为空 null 或 9i8h7g6f5e4d3c2b
Name 操作名称 process_alert
Start / End Time 纳秒级时间戳 1710000000000000000
Status Unset / Ok / Error Error(告警处理失败时)
Attributes 键值对元数据 alert_id=123, severity=critical

下面通过一个内联 SVG 展示值班机器人处理一次告警时,Span 与 Trace 的树状关系:

Trace:告警处理链路(Span 树状结构) handle_alert(根 Span) query_alert_rules enrich_alert_data send_notification db_query_rules http_get_user_info wechat_api_call 说明:每个矩形代表一个 Span,箭头表示父子关系。根 Span handle_alert 包含三个子 Span,其中 query_alert_rules 和 send_notification 各自包含一个孙 Span。

2.4 Context(上下文)—— 跨进程传播的纽带

Context 是 OpenTelemetry 实现分布式追踪的核心机制。它通过 W3C Trace Context 标准协议,在服务之间传递追踪状态。Context 主要包含两个关键字段:

  • traceparent:格式为 00-{trace_id}-{span_id}-{trace_flags},例如 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01。
  • tracestate:用于携带厂商自定义的键值对,例如 vendor=otel,tenant=prod。
传播流程: 服务 A 在处理请求时创建 Span,将 Context 注入到 HTTP 头中;服务 B 收到请求后从 HTTP 头中提取 Context,创建子 Span 并关联到同一个 Trace。值班机器人在调用告警通知 API 时,必须确保 Context 正确传递,否则链路会断裂。

2.5 Resource(资源)—— 数据来源的身份证

Resource 用于描述产生可观测性数据的实体,通常包含服务名称、版本、主机信息、云环境等。OpenTelemetry 定义了标准的资源语义约定:

资源属性 说明 值班机器人示例
service.name 服务名称 alert-bot
service.version 服务版本 2.1.0
host.id 主机唯一标识 i-0abcd1234efgh5678
deployment.environment 部署环境 production
cloud.region 云区域 cn-north-1

Resource 在告警聚合中的价值在于:当多个值班机器人实例同时运行时,可以通过 Resource 属性区分不同实例产生的数据,实现按服务、环境或主机维度的告警聚合分析。

2.6 Instrumentation(插桩)—— 自动化观测的入口

Instrumentation 是 OpenTelemetry 提供的标准化接入方式,分为 自动插桩 和 手动插桩 两种模式。在值班机器人项目中,推荐采用混合策略:

  • 自动插桩:通过 Python Agent 或库的自动补丁(monkey-patch)拦截 HTTP 请求、数据库调用、消息队列等常见操作,零代码生成基础 Span。
  • 手动插桩:在关键业务逻辑(如告警规则匹配、通知发送策略)中显式创建 Span,添加业务属性,实现精细化追踪。

下面通过一个内联 SVG 展示自动插桩与手动插桩在值班机器人中的协作关系:

Instrumentation 插桩模式:自动 + 手动协作 自动插桩(Agent 层) HTTP 请求拦截 数据库查询拦截 消息队列拦截 gRPC 调用拦截 手动插桩(业务层) 告警规则匹配 通知策略选择 告警去重逻辑 通知发送重试 数据传递 说明:自动插桩覆盖基础设施层,手动插桩覆盖业务逻辑层。两者通过 Context 共享同一个 Trace,实现从网络请求到业务决策的完整追踪。

2.7 核心概念在值班机器人中的协作流程

为了更直观地理解这六个概念如何协同工作,下面给出一个完整的 Python 代码示例,展示值班机器人在处理告警时如何创建 Span、传递 Context 并附加 Resource:

from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter

# 1. 定义 Resource(资源)
resource = Resource.create({
    "service.name": "alert-bot",
    "service.version": "2.1.0",
    "deployment.environment": "production"
})

# 2. 配置 TracerProvider
provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://otel-collector:4317"))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)

tracer = trace.get_tracer(__name__)

# 3. 手动插桩:创建根 Span
with tracer.start_as_current_span("handle_alert") as root_span:
    root_span.set_attribute("alert_id", "alert-12345")
    root_span.set_attribute("severity", "critical")

    # 自动插桩会在此 Span 下自动创建 HTTP 子 Span
    # 手动插桩:创建业务子 Span
    with tracer.start_as_current_span("query_alert_rules") as child_span:
        child_span.set_attribute("rule_count", 5)
        # 执行数据库查询(自动插桩会拦截)

    with tracer.start_as_current_span("send_notification") as child_span2:
        child_span2.set_attribute("channel", "wechat")
        # 调用通知 API(自动插桩会拦截并传递 Context)

    # 4. 模拟错误场景
    root_span.set_status(trace.Status(trace.StatusCode.ERROR, "通知发送超时"))
常见陷阱: 在手动插桩中忘记设置 set_status 会导致错误 Span 无法被正确识别;Resource 属性必须在 TracerProvider 初始化时设置,后续无法修改;Context 传递依赖 HTTP 头或 gRPC 元数据,如果使用异步消息队列(如 Kafka),需要手动注入和提取 Context。

2.8 小结