深入 OpenTelemetry 16:Histogram 的桶不是精确分位数
有六个延迟,能求出准确 P95 吗?
固定延迟 [0, 10, 11, 20, 50, 70] 毫秒,count=6、sum=161。若选择显式边界 [10,20,50],采集得到四个桶 [2,2,1,1];仅凭这四个数字,不能还原每条请求的延迟,更无法精确还原 P95。桶累计的是落在哪个范围的次数,而不是原始样本列表。
| 值 | 桶(显式边界) | 次数 |
|---|---|---|
| 0、10 | ≤10 | 2 |
| 11、20 | (10,20] | 2 |
| 50 | (20,50] | 1 |
| 70 | >50 | 1 |
两种桶的数据对象和源码路径
以下为对 Java SDK 完整 SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020 的静态阅读。Aggregation.explicitBucketHistogram 可以设置显式边界;默认 histogram 使用该类聚合,默认桶不是本次自定义的 [10,20,50]。DoubleExplicitBucketHistogramAggregator.Handle 维护 count/sum/桶;ExplicitBucketHistogramUtils.findBucketIndex 确定等于边界的值落在哪个桶。HistogramPointData 分别暴露总数、总和、边界与桶计数,不暴露任意原始延迟数组。
Aggregation.base2ExponentialBucketHistogram 选择指数桶,maxBuckets 限制每侧桶数,值跨度增加时 DoubleBase2ExponentialHistogramAggregator 必要时降低 scale。ExponentialHistogramPointData 包含 scale、zeroCount、正负桶,桶边界需结合 ExponentialHistogramBuckets.getOffset 解释,不能把 bucket 数组下标直接当延迟值。此处记录的是非负延迟;SdkLongHistogram.record 会忽略负值。上游 SdkLongHistogramTest 还覆盖了指数桶在 delta/cumulative 下的 scale 行为,本次不验证缩放前后转换。
本地双仪表实验
Lab16Test 将同一组六个值写入两个 instrument,记录时不传属性(默认空属性集合),分别用 View 指定显式桶 [10,20,50] 和指数桶 (maxBuckets=8,maxScale=0)。全部写入后采集一次,逐字段断言:显式 [2,2,1,1]、count=6、sum=161;指数数据 count=6、sum=161、zeroCount=1、positiveBuckets 总数 5、negativeBuckets 总数 0、scale=0。手动采集不涉及导出时分位数重建。
在 examples/opentelemetry-java/ 运行 JAVA_HOME=/tmp/otel-20260930/jdk-extract/usr/lib/jvm/java-21-openjdk-amd64 ./mvnw -q -pl sdk-labs -Dtest=Lab16Test test,退出码 0,原始 stdout:
1 | |
断言代码见 examples/opentelemetry-java/sdk-labs/src/test/java/org/example/otel/Lab16Test.java,环境记录见 examples/opentelemetry-java/evidence/16/RUN.md。
误解、估计与练习
“一个桶里的观测都等于桶上界”是错误推断;上界只是范围条件。即使后端可用直方图估算分位数,估值也受边界分辨率、跨时间窗聚合和查询实现影响。本次既没有后端,也未声称任何 P95 数字。指数桶不是自动提高精度的魔法:有限桶数跨很大数量级时会下采样降低 scale。
- 将显式边界改为
[10,50],对相同样本预先写出三个桶计数,再运行测试并修改断言;比较被合并的样本区间。 - 保留边界但将 70 替换为 10000,保持 count=6,观察指数桶
scale、offset、正桶计数是否变化;不得将桶数变化理解成记录数丢失。
参考资料:固定 SHA 的 Aggregation、两种 aggregator、两种 PointData 及上游 SdkLongHistogramTest(链接见正文);本地证据 examples/opentelemetry-java/evidence/16/RUN.md。
导航:15 Reader 与 Temporality · 当前篇:16 Histogram · 17 Exemplar。
