深入 OpenTelemetry 26:Collector 接收成功为何不等于后端查得到
SDK 的 OTLP exporter 返回成功,Trace 却在后端查询不到。排查时,至少要分开“Java 请求被 Collector 接受”“Collector 的 batch 处理”“出口发送成功”和“后端实际可查”四个事件;合并成一个布尔值,会把队列里尚未发出的数据误判成已存储。Collector 不是 Java SDK 的一部分,而是独立的 Go 进程。 本篇用 Java SDK 1.31.0、完整 JDK 21.0.12,独立运行 Collector Contrib 0.101.0 与 Jaeger all-in-one 1.57.0。两个 Go 可执行程序的归档 SHA-256 与解包二进制 SHA-256 均列于 writing-plans/opentelemetry-java/VERSIONS.md;归档经 release URL 的 HTTPS 转发取得,未获得上游签名验证,不能把“本地算了哈希”写成“发行方已认证”。Jaeger 使用内存存储,故意设置进程重启即可丢失数据的下游。 从 Java 返回值走到 Jaeger 查询 固定 Java SDK 源码 S...
深入 OpenTelemetry 27:慢请求为何仍可能被头部采样丢掉
请求结束后才知道它失败了或耗时过长;如果 Java 在创建 Span 时已经决定不记录,放在 Collector 的尾部采样器还能把它选回来吗?不能。这里有两个不同的决策位置:源端决定是否产生可导出的 Span,接收端只能从实际收到的 Span 中选择 Trace。 本篇固定 Java SDK 源码 SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020(SDK 1.31.0),完整 JDK 21.0.12。Collector Contrib 0.101.0 与 Jaeger all-in-one 1.57.0 是各自独立的 Go 进程,不属于 Java SDK;具体发行包、二进制 SHA-256 和下载信任限制记录在 writing-plans/opentelemetry-java/VERSIONS.md。实验是 SDK 直调 OTLP/HTTP exporter → Collector OTLP receiver/tail_sampling → OTLP/gRPC → Jaeger 内存后端,并非 Agent 自动插桩链路。 决策先于结果 S...
深入 OpenTelemetry 28:Java 可观测性预算怎样测量
“接了 Agent 会慢多少”没有脱离负载、采样和出口的固定答案。同一条 Java HTTP 请求,若把启动 Agent 的耗时、网络响应时间、Span 创建和异步发送混成一个数,甚至把尚未发送的排队 Span 当成后端已经保存,就算拿到漂亮的平均值也无法确定该调哪里。本篇把正确性计数和性能测量分开,公开两轮短负载的原始读数及不能外推的部分。 本次只用已有的完整 JDK 21.0.12、SDK/Agent 1.31.0、JDK HTTP 客户端与本机教学 OTLP/HTTP protobuf 接收端。Agent 发行 JAR 的 SHA-256 与 SDK SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020、instrumentation SHA 97d87f3f3b2bc61aa396d71a98387a1e857618af 都在 writing-plans/opentelemetry-java/VERSIONS.md;本文未引入 Collector 或第二套全局 SDK。 热路径在哪,后台线程又在哪 固定 SDK SHA 中,SdkSpa...
深入 OpenTelemetry 29:Trace 消失与指标图失真怎么定位
“Trace 找不到”和“指标图不对”往往只是表象。同样是看不到一条请求,可能是 Context 已断、头采根本没记录、出口路径写错、Batch 仍在队列里,也可能是接收端之后的存储问题。对指标而言,数值总计正确也可能有过多按请求 ID 拆出的曲线。本篇不虚构一次生产事故:用四组相互独立、有对照修复的 Java 故障注入,说明如何把检查点落在具体边界上。 实验固定 Java SDK/OTLP exporter 1.31.0,源码 SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020,完整 JDK 21.0.12;不新增组件。本篇出口是教学 OTLP/HTTP protobuf 接收端,指标仅用进程内 reader,不运行 Collector、Agent 或可查询后端;26–27 的另一次真实 Collector/Jaeger 查询不能替本篇背书。逐项退出码、原始断言、环境和未验证项在 examples/opentelemetry-java/evidence/29/RUN.md。 先按生成、传输、接收分层 源码层面的顺序不能倒过来。Context...
深入 OpenTelemetry E01:Reactor 切线程后父 Span 去哪了
在订阅前 Span.current() 有效,不代表 Reactor 的操作符换到另一线程后仍能读到同一个父 Span。相反,某一次自动插桩确实恢复了父上下文,也不意味着所有 CompletableFuture、虚拟线程和取消回调都自动获得相同语义。E01 要回答的是:哪个边界由代码显式传播,哪个边界由这一次固定版本的 Agent 插桩恢复? 本篇固定完整 JDK 21.0.12、SDK 1.31.0(源码 SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020)、instrumentation/Agent 1.31.0(源码 SHA 97d87f3f3b2bc61aa396d71a98387a1e857618af)。新引入的仅测试依赖 io.projectreactor:reactor-core:3.6.5 与 POM 的 org.reactivestreams:reactive-streams:1.0.4;两个本机 JAR 的 SHA-256、字节码主版本及发行包信任限制见 writing-plans/opentelemetry-java/V...
深入 OpenTelemetry E02:JMS 重投时父子关系与 Link 怎么看
消息消费者的三次 receive 不一定对应三条不同的业务消息;一次回滚会把同一条消息再次交付。若硬把三次消费都写成生产 Span 的 child,就会掩盖跨时间、跨消费尝试的边界:生产与消费可以各有独立 Trace,用 Link 指向产生这条消息的 Trace。本文用真实 Java JMS 客户端和本机嵌入式 broker 重投 A,检查生产、重复消费及 Agent 发出的 Span 到底是哪种关系。 本次冻结 Java SDK 1.31.0 源码 SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020、instrumentation/Agent 1.31.0 源码 SHA 97d87f3f3b2bc61aa396d71a98387a1e857618af、完整 JDK 21.0.12。只为 E02 的测试 classpath引入 ActiveMQ Classic broker/client 5.18.3 与 jakarta.jms:jakarta.jms-api:2.0.3;后者虽然 Maven group 为 Jakarta,实际类是 jav...
深入 OpenTelemetry E03:Micrometer bridge 与 SDK 直调为什么会重复
一个业务计数器已经挂在 Micrometer MeterRegistry 上,又在同一处理函数直接调用 OpenTelemetry SDK 计数器;两个路径都叫 duplicate.orders。此时看到两条点,是 bridge 内部重试、reader 重复导出,还是业务代码真正记录了两次?答案要从记录入口和 instrumentation scope 入手,不能只看指标名。 本篇固定 Java SDK 1.31.0 源码 SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020、instrumentation bridge 1.31.0-alpha 源码 SHA 97d87f3f3b2bc61aa396d71a98387a1e857618af。测试 classpath 上引入 Micrometer Core 1.12.5 与桥接 JAR,具体 artifact/JAR SHA-256 在 writing-plans/opentelemetry-java/VERSIONS.md。本机完整 JDK 21.0.12 执行测试;没有挂 Agent,也没有...
深入 OpenTelemetry E04:JMX 的 JVM 指标在什么时候采集
在监控图上看到 JVM 内存池用量和线程数,很容易把数字当作“线程刚创建时立即上报”或“分配一个 4 MiB 数组就增加 4 MiB”。指标并不这样工作:JMX 平台 MXBean 持有可查询状态,OpenTelemetry 异步 instrument 在 reader 采集时查询它;不同时间窗的状态与标签必须分开看。 版本边界是完整 JDK 21.0.12、Java SDK 1.31.0(固定源码 SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020)、instrumentation 的 runtime-telemetry-java8 library 1.31.0-alpha(固定源码 SHA 97d87f3f3b2bc61aa396d71a98387a1e857618af)。新增 JAR 的本机 SHA-256 见 writing-plans/opentelemetry-java/VERSIONS.md。这个 library 从当前 JVM 的平台 MXBean 取值,实验没有启动独立远程 JMX collector,也没有挂 Agent。...
深入 OpenTelemetry E05:升级 Agent 时自定义扩展还工作吗
把 -javaagent 的 JAR 从 1.31.0 换成 1.32.0,应用仍能拿到非空的 GlobalOpenTelemetry,并不等于自定义扩展被加载、默认采样保持不变或后端收到数据。版本回归至少要把发行 JAR、应用 API classpath、Agent 内部 SDK 与扩展 JAR 分开核对,然后在独立 JVM 里重复同一套断言。 这次固定两对上游源码:旧 Java SDK SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020 / instrumentation SHA 97d87f3f3b2bc61aa396d71a98387a1e857618af;新 SDK SHA ff2e1638caee86120b0ad0e3bd3c2af68d07ae4e / instrumentation SHA a36175cb65e8fe48a4da388d1c87288701e1b7ad。Maven Agent 发行 JAR 1.31.0/1.32.0 及本仓库 extension-lab JAR 的实际 SHA-256 见 writing-...
分布式系统(E08):从微秒 RPC 到尾延迟追踪
一次请求的平均延迟很低,p99却不断升高。trace瀑布图里某个服务占了四十毫秒,于是它被判为根因。这个诊断可能同时错在三处:请求要等待的完成条件没有写清,压测器在慢响应期间停止发新请求,跨主机时间戳又被当成了因果顺序。 eRPC说明了专用数据中心RPC如何把软件开销压低;尾延迟研究解释了罕见慢节点怎样进入用户请求;分布式追踪负责保留单次执行的关系证据。这三者解决的问题相邻,却不能彼此替代。 分布式系统(E07):控制面共识与数据面复制 延迟样本由三段协议共同产生 端到端延迟不是某个函数自带的属性。请求路径规定要等哪些分支,负载发生器决定请求何时进入,观测管线再决定哪些阶段留下记录。 flowchart LR A[到达模型<br/>何时产生请求] --> P[执行路径<br/>串行、fan-out、quorum] P --> Q[队列与服务<br/>等待、计算、重试] Q --> O[观测管线<br/>span、metric、profile] O --> J[结论<br/>分位数与...

