深入 OpenTelemetry 12:Instrument 选择与异步观测
同一笔请求需要几种指标?
订单服务处理两笔请求,第一笔结束时仍有另一笔在执行;两笔延迟分别是 10、30 毫秒,而待处理队列当前有 2 项。若把四个事实都写成 Gauge,下一次采集就无法从当前值恢复请求总数或延迟分布。Instrument 的选择先取决于事件的数学语义:单调累计、可增减的存量、多次观测的分布,以及在采集时读取的瞬时状态。
| 事实 | 调用 | 固定事件 | 首次采集 |
|---|---|---|---|
| 已接收请求 | LongCounter.add | 1,1 |
sum=2 |
| 在途数 | LongUpDownCounter.add | +1,+1,-1 |
sum=1 |
| 延迟 | LongHistogram.record | 10,30 |
count=2、sum=40 |
| 队列长度 | ObservableLongGauge 回调 | 读取原子变量 | value=2 |
四条流都显式传入 route=/orders;同名但不同属性的记录属于不同数据点。这里的队列 2 不是累计发生过两次入队;第二次采集将它更新为 5,请求总数仍为 2。
源码路径:写入与采集不在同一时间
以下为对 Java SDK c25c0a0ee0da01ab2f74ba83052d1c249ed57020 的静态阅读,不是本地运行结果。SdkMeterProvider.meterBuilder 在无 reader 时使用 no-op meter;本实验注册 InMemoryMetricReader 后才有可读的流。SdkMeter 委托共享状态执行采集。SdkLongCounter.add 拒绝负值并记录警告,不是自动转成 UpDownCounter;SdkLongUpDownCounter.add 接受负增量;SdkLongHistogram.record 忽略负观测值。add/record 将值和上下文交给 storage;桶与属性处理留到后续篇目。
异步仪表的回调由 MeterSharedState.collectAll 在采集路径执行;注册列表使用锁保护,采集路径另有 collectLock,CallbackRegistration.invokeCallback 捕获回调异常并记录警告。测试使用原子变量提供跨线程可见性,但手动 reader 的回调在本次调用 collectAllMetrics() 的路径上完成,不需要定时器或睡眠。上游 SdkLongGaugeTest 还验证关闭回调后不再导出该流。不能由此推断任意生产环境读者都在业务线程执行回调。上游 SdkLongCounterTest、SdkLongUpDownCounterTest 与 SdkLongHistogramTest 分别检查默认单调性、非单调性及聚合点;这些测试属于上游静态阅读,不是本地 JUnit 执行。
本地固定序列
运行完整 JDK 21 下的 JAVA_HOME=/tmp/otel-20260930/jdk-extract/usr/lib/jvm/java-21-openjdk-amd64 ./mvnw -q -pl sdk-labs -Dtest=Lab12Test test(在 examples/opentelemetry-java/ 内),退出码 0,原始摘要:
1 | |
Lab12Test 对 MetricData 的值、route 属性和两次采集结果分别断言,不是从摘要字符串推算。测试代码位于 examples/opentelemetry-java/sdk-labs/src/test/java/org/example/otel/Lab12Test.java;环境和判定见 examples/opentelemetry-java/evidence/12/RUN.md。这只是内存 reader 的进程内观测,未发送指标 OTLP。
误解、练习与边界
Gauge 表示采集时观测到的值,不等于 Counter 的“累积到当前”;UpDownCounter 的负数是正常增量,Counter 的负数会被忽略;Histogram 的 sum/count 不自动给出准确分位数。Gauge 回调可能被不同 reader 触发,回调不宜阻塞或产生副作用。本篇未验证多线程写入、基数上限或跨采集时间窗的 temporality。
- 修改
Lab12Test,在第二次采集前添加第三次请求,并显式断言请求数变成 3,队列观测仍由当前原子值决定;保留两个采集点的对照。 - 把
requests.add(1)后面改为requests.add(-1)构造反例,断言仍为 2,结合上面SdkLongCounter.add的负值分支解释原因;不要将日志警告当成采集成功。
参考资料:固定 SHA 的 SdkMeterProvider、SdkMeter、三个同步 instrument、MeterSharedState 和上游 SdkLongGaugeTest(链接见正文);版本冻结见 writing-plans/opentelemetry-java/VERSIONS.md。
导航:11 Flush 与 Shutdown · 当前篇:12 Instrument 选择 · 13 记录与聚合。
