我正在Web服务中使用Prometheus Java simpleclient来跟踪导致一个状态或另一状态的事件数量。
我能够在日志中检查计数器是否正在被调用并在内部递增,但是似乎很多时候该数据并未到达/ metrics端点。
例如,刚才,将计数器递增3次(对于相同状态,每次间隔几分钟)后,日志将打印出“当前值= 0,新值= 1”三次。前两次没有在/ metrics端点上显示任何数据,并且在第三个增量之后,最终显示的值为1,这意味着我丢失了前2个事件的记录。
除了一些名称更改之外,我下面的代码如下。
private static final Counter myCounter = Counter.build()
.name("myMetric")
.help("My metric")
.labelNames("status").register();
...
private static void incrementCounter(String status) {
Counter.Child counter = myCounter.labels(status);
Logger.info("Before Incrementing counter for status= " + status + ". Current value=" + counter.get());
counter.inc();
Logger.info("After Incrementing counter for status= " + status + ". New value=" + counter.get());
}
为什么Prometheus似乎无法始终如一地跟踪这些计数器,我感到茫然。有人能看到什么地方出了问题或记录这些计数器指标的更好方法吗?
答案 0 :(得分:0)
我能猜到的唯一原因是并发incrementCounter
调用。
io.prometheus.client.SimpleCollector#labels
方法不是线程安全的(尽管children
字段具有ConcurrentMap
类型),因此每次调用都可能获得不同的io.prometheus.client.Counter.Child
。
关于通过http获取度量标准-每次对/metrics
端点的调用都会导致io.prometheus.client.Counter#collect
方法调用,该方法将检索唯一一个孩子的值。
我建议您使用自己的并发映射来存储计数器:
private static final ConcurrentMap<String, Counter.Child> counters = new ConcurrentHashMap<>();
// ...
private static void incrementCounter(String status) {
Counter.Child counter = counters.computeIfAbsent(status, myCounter::labels) ;
// ...
}