同一个 Counter,为什么会有两个点?

四个工作线程分别接收 50 笔请求,两个线程标注 region=east,两个标注 region=west。期望导出的不是一条值 200 的流,也不是四条值 50 的流,而是两个属性集合对应的点,各有 100 次写入。record/add 不直接发送网络请求;它在与 instrument 和 reader 对应的存储中更新聚合状态。

聚合键 写入线程 Counter sum Histogram count / sum
region=east 2 × 50 次 100 100 / 1000
region=west 2 × 50 次 100 100 / 1000

沿固定源码走一遍

以下均是对 Java SDK 1.31.0 完整 SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020 的静态阅读。SdkLongCounter.add 校验非负后将值、属性、上下文交给 storage。DefaultSynchronousMetricStorage.recordLong 先取对应 handle。getAggregatorHandle 先处理属性再作为 ConcurrentHashMap<Attributes, ...> 的键,相同处理后属性的线程共享 handle;超出上限时转入特殊溢出键而非无限建点。此篇只传固定两个 region,溢出行为留给 14。

LongSumAggregator.Handle 使用 LongAdder,doRecordLong 累加,采集时根据是否 delta 执行 sumThenReset 或 sum。DefaultSynchronousMetricStorage.collect 枚举 handle 形成 MetricData;这个 forEach 与并发写入不能视为全局事务性快照。InMemoryMetricReader.create() 默认为 cumulative,固定输入先完成再 collect,才可直接断言所有已发生的加法。上游 LongSumAggregatorTest 对聚合与 reset 分支分别做了检查;不能把“线程安全写入”混同于“任意时点跨所有键一致读取”。

已知输入与本地输出

Lab13Test 用 CountDownLatch 同时放行四线程;每个线程先确定 region 属性,再为一个 Counter 增 1、为一个 Histogram 记录 10,各 50 次。主线程使用有期限的 Future.get(10, SECONDS) 等待所有写入完成,才调用手动 reader 采集。每个地区对应 count=100、sum=1000,没有依赖调度顺序或 sleep。

在 examples/opentelemetry-java/ 内运行 JAVA_HOME=/tmp/otel-20260930/jdk-extract/usr/lib/jvm/java-21-openjdk-amd64 ./mvnw -q -pl sdk-labs -Dtest=Lab13Test test,退出码 0,原始 stdout:

1
LAB13 threads=4 events=200 regions=2 sum=100+100 histogram=count:100+100,sum:1000+1000

代码直接检查两个点的属性和值,具体断言见 examples/opentelemetry-java/sdk-labs/src/test/java/org/example/otel/Lab13Test.java,命令与范围见 examples/opentelemetry-java/evidence/13/RUN.md。这里的 sum 是每个地区的延迟观测和,不是四线程的全局请求数,也不是单位时间速率。

容易混淆的边界与练习

“每次 add 生成一个点”不成立;先按属性聚合再采集。“ConcurrentHashMap 就使采集与写入成为原子快照”也不成立,本实验故意等线程结束后才采集。属性处理 View、delta reader 和溢出都可能改变点与值,不能直接套用此处的 100+100。

  1. 修改 Lab13Test,让一个 east worker 的属性换成 region=north,预期变成三个点(east=50、north=50、west=100),调整属性与 sum/count 断言,不仅检查集合大小。
  2. 将采集提前至闩锁放行后、Future 全部完成前,思考为什么一次运行结果不足以证明跨两种仪表的快照一致性;恢复等待屏障后再比较。

参考资料:固定 SHA 的 SdkLongCounter、DefaultSynchronousMetricStorage、LongSumAggregator 及其上游单测(链接见正文);本地证据 examples/opentelemetry-java/evidence/13/RUN.md。

导航:12 Instrument 选择 · 当前篇:13 记录与聚合 · 14 View 与基数。