news 2026/9/12 11:03:02

使用 OpenTelemetry Collector Builder 定制 Jaeger 发行版:components/ 公共 API 与 ocb 装配实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 OpenTelemetry Collector Builder 定制 Jaeger 发行版:components/ 公共 API 与 ocb 装配实战

使用 OpenTelemetry Collector Builder 定制 Jaeger 发行版:components/ 公共 API 与 ocb 装配实战

【免费下载链接】jaegerCNCF Jaeger, a Distributed Tracing Platform项目地址: https://gitcode.com/GitHub_Trending/ja/jaeger

Jaeger V2 已全面基于 OpenTelemetry Collector 构建,而components/目录正是面向外部开发者开放的一组公共 API,用于通过 ocb(OpenTelemetry Collector Builder)自由拼装属于自己的 Jaeger 发行版。本文将围绕 components/README.md 展开,深入解读目录布局、双重派发模式与第三方组件别名机制,并结合 cmd/jaeger/builder.yaml 与 cmd/jaeger/internal/components.go 的源码证据,给出从零编写 builder.yaml 到产出可运行二进制的完整实战方案。

components/ 目录的定位:自定义发行版的公共 API

Jaeger 的“定制发行版”(custom distribution)机制由来已久,其设计决策记录在 docs/adr/011-custom-distributions.md 中。简单来说,Jaeger 希望开发者不必 fork 整个仓库、不必改动 Jaeger 核心代码,就能通过一份清单文件把需要的组件(receiver、processor、exporter、extension、connector、telemetry)组装成一个全新的、可独立发布的二进制。

components/目录就是这个机制对外暴露的唯一公共面。正如其 README 开头所写,该目录提供的是"构建自定义 Jaeger 发行版的公共 API",核心工具是 ocb(OpenTelemetry Collector Builder)。ocb 读取一份builder.yaml清单,自动生成并编译一个仅包含清单中所列组件的 Collector 二进制——Jaeger V2 的默认发行版正是用同一套流程产出的。

与这一目标相对应,components/目录内部刻意做了职责切分:

  • 顶层包extension/exporter/processor/telemetry/):Jaeger 专属组件,即只存在于 Jaeger 生态、由 Jaeger 自己维护实现的组件;
  • ext/:第三方 OTel Collector 组件,来自 otel-contrib 与 collector core,仓库内只保留"一行别名"式的转发声明;
  • cmd/jaeger/components/:位于cmd/jaeger子树内的桥接层,负责突破 Gointernal包访问限制(详见下文"双重派发"一节)。

目录布局解读:两层结构,各司其职

顶层包:Jaeger 专属组件与双重派发模式

顶层包包括components/extension/components/exporter/components/processor/components/telemetry/,容纳的是 Jaeger 自研组件,例如:

  • extension/jaegerstorage:接入 Jaeger 存储后端(Cassandra、Elasticsearch、Badger 等)的扩展;
  • extension/jaegerquery:提供 Jaeger Query 服务的扩展;
  • extension/remotesampling:远程采样策略管理扩展;
  • extension/expvar:暴露 Goexpvar指标;
  • extension/remotestorage:远程存储服务扩展;
  • exporter/storageexporter:通用的"写入 Jaeger v1 spanstore.SpanWriter"导出器;
  • processor/adaptivesampling:自适应采样处理器;
  • telemetry:Jaeger 的遥测工厂。

这些组件之所以需要一套特殊的"双重派发"(double-dispatch)结构,根因是Go 语言的internal包访问限制:只有位于cmd/jaeger/子树内的代码才能导入cmd/jaeger/internal/,而公共的components/目录在该子树之外,无法直接引用内部实现。为此,仓库在cmd/jaeger/components/下放置了一层桥接包,每个包只有一个小小的factory.go,例如 cmd/jaeger/components/extension/jaegerstorage/factory.go:

package jaegerstorage import impl "github.com/jaegertracing/jaeger/cmd/jaeger/internal/extension/jaegerstorage" var NewFactory = impl.NewFactory

而公共门面(facade)再对这一桥接层做一次别名转发,例如 components/extension/jaegerstorage/factory.go:

package jaegerstorage import impl "github.com/jaegertracing/jaeger/cmd/jaeger/components/extension/jaegerstorage" var NewFactory = impl.NewFactory

这样便形成了一条完整的调用链:公共门面 → 桥接层 → 内部实现。外部使用者只依赖components/下的公共包,内部实现细节则始终被internal规则保护。桥接层的设计说明完整记录在 cmd/jaeger/components/README.md 中。

ext/:第三方组件的一行别名

与 Jaeger 专属组件不同,来自 otel-contrib 与 collector core 的第三方组件完全绕开双重派发,通过components/ext/直接转发上游工厂。这些包同样是"一行别名",例如 components/ext/extension/healthcheckv2extension/factory.go:

package healthcheckv2extension import impl "github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckv2extension" var NewFactory = impl.NewFactory

这种做法带来的关键收益是版本一致性builder.yaml里所有第三方组件都可以通过同一个gomod条目(github.com/jaegertracing/jaeger)被引用,而无需逐个锁定上游组件的版本。各第三方组件的真实版本由 Jaeger 自己的go.mod传递解析,从而保证整个发行版内组件的版本互相兼容、同步升级。

用 ocb 构建发行版:builder.yaml 的写法

最小示例:公共 API 的使用方式

在自定义发行版的builder.yaml中,只需按 ocb 的清单格式引用上述公共包即可。以下示例摘自 components/README.md:

extensions: - gomod: github.com/jaegertracing/jaeger v2.19.0 import: github.com/jaegertracing/jaeger/components/extension/jaegerstorage - gomod: github.com/jaegertracing/jaeger v2.19.0 import: github.com/jaegertracing/jaeger/components/ext/extension/healthcheckv2extension

两个字段的含义:

  • gomod:ocb 生成 go.mod 时使用的模块标识与版本。所有组件统一指向github.com/jaegertracing/jaeger及其某个发布版本(如v2.19.0),第三方组件的实际版本由此传递解析;
  • import:该组件的 Go 导入路径,即上文components/下对应包的路径。

完整参考清单:cmd/jaeger/builder.yaml 逐节解析

cmd/jaeger/builder.yaml 是官方提供的完整参考清单,它精确复刻了 Jaeger 默认生产发行版的组件集合,同时充当文档与 CI 校验产物。其头部注释明确说明:清单中的组件列表与标准二进制使用的internal.Components()完全一致;而像storagecleaner这类仅用于测试的组件则两者都不包含,由 cmd/jaeger/internal/integration/jaeger-e2e 单独注册。

清单的顶层结构如下:

区块说明组件数量
dist发行版自身的模块名、二进制名、输出路径1
telemetry遥测工厂1
extensions扩展(含认证、健康检查、存储、采样等)10
receivers接收器(OTLP、Jaeger、Kafka、Zipkin 等)5
exporters导出器(调试、OTLP、Kafka、Prometheus、存储等)7
processors处理器(批处理、内存限制、尾采样、自适应采样等)6
connectors连接器(forward、spanmetrics)2
replaces仓库内构建时的本地替换指令1

各区块的完整内容(已按官方清单整理):

dist: module: github.com/jaegertracing/jaeger/cmd/jaeger/ocb-build name: jaeger description: Jaeger - distributed tracing platform output_path: ./cmd/jaeger/_build telemetry: gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/telemetry extensions: - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/extension/healthcheckv2extension - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/extension/pprofextension - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/extension/zpagesextension - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/extension/basicauthextension - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/extension/sigv4authextension - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/extension/jaegerquery - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/extension/jaegerstorage - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/extension/remotesampling - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/extension/expvar - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/extension/remotestorage receivers: - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/receiver/otlpreceiver - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/receiver/nopreceiver - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/receiver/jaegerreceiver - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/receiver/kafkareceiver - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/receiver/zipkinreceiver exporters: - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/exporter/debugexporter - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/exporter/otlpexporter - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/exporter/otlphttpexporter - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/exporter/nopexporter - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/exporter/storageexporter - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/exporter/kafkaexporter - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/exporter/prometheusexporter processors: - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/processor/batchprocessor - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/processor/memorylimiterprocessor - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/processor/tailsamplingprocessor - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/processor/attributesprocessor - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/processor/filterprocessor - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/processor/adaptivesampling connectors: - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/connector/forwardconnector - gomod: github.com/jaegertracing/jaeger v0.0.0 import: github.com/jaegertracing/jaeger/components/ext/connector/spanmetricsconnector replaces: - github.com/jaegertracing/jaeger v0.0.0 => ../../../

注意清单头部注释中的两个关键约定:

  • 仓库内构建:所有组件使用github.com/jaegertracing/jaeger v0.0.0作为gomod,配合replaces指令指向本地源码,这是为了在仓库内直接编译;
  • 外部使用:外部用户应把v0.0.0替换为真实发布版本(例如v2.19.0),并删除replaces指令,让依赖从上游模块解析。

源码级装配原理:从清单到可运行二进制

builder.yaml描述的组件集合,与标准二进制实际注册的组件严格一一对应,这一对应关系在 cmd/jaeger/internal/components.go 的Components()函数中得到印证。该函数通过defaultBuilders().build()依次构造五类工厂映射:

  • Extensions:标准部分(healthcheckv2、pprof、zpages)与"add-ons"(basicauth、sigv4auth、jaegerquery、jaegerstorage、remotesampling、expvar、remotestorage);
  • Receivers:标准部分(otlp、nop)与 add-ons(jaeger、kafka、zipkin);
  • Exporters:标准部分(debug、otlp、otlphttp、nop)与 add-ons(storageexporter——注释明确标注为"通用的 Jaeger v1 spanstore.SpanWriter 导出器"、kafka、prometheus),并保留了一行被注释掉的elasticsearch.NewFactory(),说明该组件当前未纳入默认发行版;
  • Processors:标准部分(batch、memorylimiter、tailsampling、attributes、filter)与 add-ons(adaptivesampling);
  • Connectors:标准部分(forward)与 add-ons(spanmetrics)。

所有工厂对象均来自components/公共包(import语句直接引用了github.com/jaegertracing/jaeger/components/...),这正验证了 README 所述——公共目录是唯一被内外共同消费的组件来源。ocb 生成的发行版在运行时按同样的工厂映射装配组件,只是入口从internal.Components()换成了清单驱动的代码生成。

构建命令与跨平台编译

参考清单的头部注释给出了完整的构建方式。在仓库内执行:

ocb --config cmd/jaeger/builder.yaml

ocb 会根据dist.output_path./cmd/jaeger/_build)生成编译产物。跨平台编译通过 Go 标准的环境变量完成:

GOOS=linux GOARCH=arm64 ocb --config cmd/jaeger/builder.yaml

ocb 生成的二进制即为一个独立的 Jaeger 发行版,之后用 Jaeger V2 的配置文件(例如 cmd/jaeger/config.yaml)即可启动。仓库还提供了 cmd/jaeger/config-ocb-smoketest.yaml,用于对 ocb 产物做冒烟测试,可视为清单与配置联动的官方验证示例。

定制实战:如何添加自定义组件

ocb 清单的价值正在于"增删组件、重塑发行版"。官方推荐的做法是:复制 cmd/jaeger/builder.yaml,在相应区块末尾追加条目(extensions、receivers、exporters、processors、connectors 各有独立区块),然后运行 ocb 构建。

对于想深入了解"自定义组件长什么样"的读者,仓库内自带一个真实范例:components/extension/queryinterceptorexample/(含 factory.go、config.go、extension.go 及配套的 config-query-interceptor.yaml 与集成测试),演示如何编写一个拦截 Jaeger Query 请求的自定义扩展,是学习"如何为自定义发行版编写 Jaeger 专属组件"的最佳入门素材。

在动手定制时还需要留意以下事实(均可在清单注释与源码中验证):

  • 若引入的是 Jaeger 自研组件,必须遵循components/下的双重派发模式,确保内部实现不被internal规则阻断;
  • 若引入的是上游 OTel 第三方组件,应参照components/ext/的别名写法,统一通过github.com/jaegertracing/jaeger这一个gomod条目引用,保持版本一致性;
  • 测试专用组件(如storagecleaner)既不在builder.yaml也不在internal.Components()中,而是由 cmd/jaeger/internal/integration/jaeger-e2e 按需注册,因此生产发行版不应包含此类组件。

综上,components/目录 + ocb 的组合构成了 Jaeger 自定义发行版的完整工作流:公共 API 提供稳定的组件契约,ext/别名保证上游组件版本随 Jaeger 整体对齐,builder.yaml清单则让开发者用最少的配置组合出自己的分发二进制。无论是裁剪默认发行版、加入私有组件,还是构建面向特定存储与网络环境的专用版本,这套机制都能在不修改 Jaeger 核心的前提下完成。

【免费下载链接】jaegerCNCF Jaeger, a Distributed Tracing Platform项目地址: https://gitcode.com/GitHub_Trending/ja/jaeger

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 11:02:16

guzzlehttp/guzzle库和CURL的区别是什么?

guzzlehttp/guzzle库和CURL的区别是什么?guzzlehttp/guzzle和CURL都是用来发送HTTP请求的工具,但它们之间有一些重要的区别。易用性:CURL是一个命令行工具,也提供了PHP的扩展接口。使用CURL时,你需要设置一系列的选项来…

作者头像 李华
网站建设 2026/9/12 11:02:05

LangChain高并发智能客服的流控与语义降级实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 11:01:45

雪雁算法优化大规模多旅行商问题的MATLAB实现

1. 项目背景与问题定义大规模单仓库多旅行商问题(Large-Scale Single-Depot Multiple Traveling Salesman Problem, LS-SDMTSP)是经典TSP问题的扩展变种,在物流配送、无人机巡检、电网维护等领域具有广泛应用。与标准TSP不同,该问…

作者头像 李华
网站建设 2026/9/12 11:00:46

用AI把课程视频转成结构化讲义:原理、工具与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华