OpenTelemetry OpenTelemetry

使用声明式 YAML 文件配置 SDK

在 SDK 支持的地方,用一个带 OTEL_CONFIG_FILE 的 YAML 文件取代几十个环境变量。

10 min 中级

环境变量适合处理少量设置,但当你需要多个 exporter、自定义 processor 或采样规则时,它们就变得笨重了。声明式配置用一个 YAML 文件取而代之,描述整个 SDK:资源、propagator,以及 tracer、meter 和 logger provider。该 schema 在 2026 年达到了稳定版本,这意味着围绕它进行设计是安全的。各个 SDK 的支持仍然参差不齐,所以在采用之前请阅读状态一节。

开启它

保存一个文件,并用一个环境变量将 SDK 指向它:

export OTEL_CONFIG_FILE=/etc/otel/otel-config.yaml

当设置了 OTEL_CONFIG_FILE 时,支持声明式配置的 SDK 会根据该文件构建自己。除非文件引用了其他 OTEL_* 变量,否则这些变量随后都会被忽略,下面会介绍。

一个完整的示例

otel-config.yaml:

file_format: "1.2"

resource:
  attributes_list: ${OTEL_RESOURCE_ATTRIBUTES}
  detection/development:
    detectors:
      - service:
      - host:
      - process:
      - container:

propagator:
  composite:
    - tracecontext:
    - baggage:

tracer_provider:
  sampler:
    parent_based:
      root:
        always_on:
  processors:
    - batch:
        exporter:
          otlp_http:
            endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4318}/v1/traces

meter_provider:
  readers:
    - periodic:
        exporter:
          otlp_http:
            endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4318}/v1/metrics

logger_provider:
  processors:
    - batch:
        exporter:
          otlp_http:
            endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4318}/v1/logs

请使用你的 SDK 文档所指定的 file_format 值,因为各 SDK 采纳新 schema 版本的时间不同。如何阅读这个文件:

  • resource 描述服务。attributes_list 接受通常的 key=value,key=value 字符串,而 detectors 会自动添加主机、进程和容器信息。以 /development 结尾的属性仍是实验性的,可能并非每个 SDK 中都存在。
  • propagator 列出上下文 propagator,这里是 W3C trace context 和 baggage。
  • tracer_provider 包含采样器和 span processor。这里一个 batch processor 通过 OTLP HTTP exporter 发送 span。
  • meter_provider 包含指标 reader。periodic reader 按间隔导出。
  • logger_provider 对日志做同样的事。
  • otlp_http 与 otlp_grpc:交换 exporter 名称和端点(gRPC 用 http://localhost:4317)即可更换协议。

环境变量替换

在文件内部,${VAR} 读取环境变量,${VAR:-default} 在变量未设置时提供默认值。环境变量在其他情况下会被忽略,这正是关键所在:除非文件要求,否则没有任何东西会改变行为。这使得很容易看出每个环境下有哪些是可配置的:

resource:
  attributes_list: ${OTEL_RESOURCE_ATTRIBUTES}

tracer_provider:
  processors:
    - batch:
        exporter:
          otlp_http:
            endpoint: ${OTEL_EXPORTER_OTLP_TRACES_ENDPOINT:-http://localhost:4318/v1/traces}

这样同一个文件在开发环境(默认值)和生产环境(由平台设置变量)中都能工作。

按信号的目的地与更丰富的配置

声明式配置在环境变量难以很好表达的事情上大放异彩,比如把相同的 span 发送到两个地方,或调整某个 processor:

tracer_provider:
  processors:
    - batch:
        schedule_delay: 2000
        max_queue_size: 4096
        exporter:
          otlp_http:
            endpoint: http://collector:4318/v1/traces
    - simple:
        exporter:
          console:

这里 span 以批的方式发送到 Collector,同时也打印到控制台,这对本地调试很有用。请查看你的 SDK 文档,了解它所支持的确切属性名称,因为可用的 processor、采样器和 exporter 取决于具体实现。

哪些语言支持它

规范和 schema 是稳定的,但每种语言按自己的节奏实现它们:

  • 可用: C++、Go、Java、JavaScript 和 PHP 有实现,Java agent 记录了它自己的设置。
  • 开发中: .NET 和 Python。
  • 文档仍将各实现中的支持描述为实验性的,所以请在依赖它之前,为你的语言测试这个功能。
  • Collector 本身使用 Go 实现来配置它自己的内部遥测。

如果你的语言还没准备好,请继续使用环境变量。这两种模型被有意设计为相互兼容:替换示例中所示的变量名,与你不用文件时所使用的是同样的名称。

在两者之间选择

在以下情况使用环境变量在以下情况使用声明式文件
你为每个服务设置少量选项你需要多个 exporter 或 processor
你的平台已经注入环境(Operator、Helm)你希望整个 SDK 设置在一个文件中得到审查
你的语言的声明式支持缺失或不成熟你希望跨多种语言使用同一种配置格式

一种合理的混合方式是从 ConfigMap 挂载一个共享文件,并让环境变量通过 ${...} 替换只提供每个环境的值。

交付文件

Docker Compose:

services:
  checkout:
    image: myorg/checkout:1.4.2
    environment:
      OTEL_CONFIG_FILE: /etc/otel/otel-config.yaml
      OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4318
      OTEL_RESOURCE_ATTRIBUTES: service.version=1.4.2,deployment.environment.name=staging
    volumes:
      - ./otel-config.yaml:/etc/otel/otel-config.yaml:ro

Kubernetes:把文件放进 ConfigMap,挂载它,并在 Deployment 中设置 OTEL_CONFIG_FILE。Git 中对 ConfigMap 的修改随后会像任何其他变更一样推出,但 SDK 在启动时读取该文件,所以请重启 Pod 以使其生效。

陷阱

  • 文件中的错误可能会阻止 SDK 启动它的 provider。请在预生产环境中测试,并在启动时观察 SDK 的日志输出(临时设置 OTEL_LOG_LEVEL=debug)。
  • 不要把 secret 直接写在文件里。使用 ${VAR},并从 Secret 注入该值。
  • 运行时动态重新配置还不是此规范的一部分。更改文件需要重启。
  • 计划弃用一些单独的环境变量,因为它们无法很好地互操作,不过被弃用并不意味着被移除。

完整的 schema 和各语言的说明,请参见声明式配置文档。

热门指南