深入 OpenTelemetry 15:Reader 的独立时间窗与 Temporality
第二次采集应得到 3 还是 5?
对请求 Counter 先加 2,采集;再加 3,采集。第二次采集的 3 与 5 都可能正确:前者是第二个增量窗口,后者是自 provider 启动以来的累计值。数值本身无法解释边界,必须同时检查 AggregationTemporality 和点的起止时间。一次采集并不意味着所有 reader 的内部聚合都被清零。
| reader | 第一次(启动→1s) | 第二次(1s→2s 或启动→2s) |
|---|---|---|
| Delta | 2,起点为 provider 创建时刻 | 3,起点为本 reader 上次采集时刻 |
| Cumulative | 2,起点为 provider 创建时刻 | 5,起点仍为 provider 创建时刻 |
SDK 如何维护这些边界
以下为固定 Java SDK SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020 的源码阅读。MetricReader 由 provider 注册后获得 CollectionRegistration,读者自己决定何时采集;SDK 提供的 InMemoryMetricReader.create() 默认为 cumulative,而 createDelta() 请求 delta。SdkMeterProvider 为每个注册 reader 初始化上次采集时刻,其 LeasedMetricProducer.produce 在采集完成后更新该 reader 的时间戳。
DefaultSynchronousMetricStorage.collect 根据 temporality 选择上次采集时间或 provider 起始时间,并在 delta 情况下重置聚合 handle。LongSumAggregator.Handle 分别使用 sumThenReset / sum。同一 instrument 对两个 reader 有各自的 storage,先采 delta 不会把 cumulative reader 的值变成零。上游 SdkLongHistogramTest 对一对 reader 的不同采集顺序与重置行为有单测。
若换为 PeriodicMetricReader,注册时调度任务在后台采集;PeriodicMetricReaderBuilder 默认间隔一分钟,setInterval 拒绝非正间隔。手动读者的时间窗不能直接冒充定时读者的网络导出行为;本篇没有运行 PeriodicMetricReader。
用时钟而不是 sleep 验证
Lab15Test 使用没有显式属性的单条流(默认空属性集合),注入 SDK testing 的 TestClock,将采集时点固定在启动后第 1 秒、第 2 秒;在两 reader 的每个点上断言 value、temporality、startEpochNanos、epochNanos。随后关闭 provider,将时钟推进到第 3 秒并重建 provider,新 Counter 写 4,第 4 秒采集从新的起点开始。这是进程内 provider 重建,不是假装测试了操作系统进程重启或下游重置检测。
在 examples/opentelemetry-java/ 运行 JAVA_HOME=/tmp/otel-20260930/jdk-extract/usr/lib/jvm/java-21-openjdk-amd64 ./mvnw -q -pl sdk-labs -Dtest=Lab15Test test,退出码 0;原始摘要:
1 | |
断言与固定事件见 examples/opentelemetry-java/sdk-labs/src/test/java/org/example/otel/Lab15Test.java,运行环境见 examples/opentelemetry-java/evidence/15/RUN.md。
误解与练习
“Delta 第二次值为 3 就意味着总请求数只有 3”错在混淆时间窗;“Cumulative 永远增长,跨重启可直接相减”忽略新的起点;“多 reader 共用一次重置”也与本实验相反。时间窗的开始和结束来自 SDK 时钟,不等于任何后端的 scrape、持久化或查询成功时点。
- 修改
Lab15Test,让 delta 在第一轮提前采集一次空窗口,然后只增加 3 再采集;调整每个startEpochNanos的预期,说明值与时间都不能省略。 - 将旧 provider 保留但换用新 reader 的想法改成明确重建 provider 的反例;比较连续 provider 的 5 与新 provider 的 4,不把差值解释成丢了一条事件。
参考资料:固定 SHA 的 MetricReader、SdkMeterProvider、DefaultSynchronousMetricStorage、LongSumAggregator、PeriodicMetricReaderBuilder 及上游测试(链接见正文);本地证据 examples/opentelemetry-java/evidence/15/RUN.md。
导航:14 View 与基数 · 当前篇:15 Reader 与 Temporality · 16 Histogram。
