普罗米修斯计数器不一致

时间:2019-03-20 18:50:58

标签: java prometheus prometheus-java

我正在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似乎无法始终如一地跟踪这些计数器,我感到茫然。有人能看到什么地方出了问题或记录这些计数器指标的更好方法吗?

1 个答案:

答案 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) ;
  // ...
}