1

我在 Web 服务中使用 Prometheus Java simpleclient 来跟踪有多少事件导致一种状态或另一种状态。

我能够在日志中检查计数器正在被调用并在内部递增,但似乎很多时候数据没有到达 /metrics 端点。

例如,刚才,对于相同的状态,每隔几分钟将计数器递增 3 次后,日志将打印 3 次“当前值 = 0,新值 = 1”。前两次在 /metrics 端点上没有显示任何数据,在第 3 次增量之后,它最终显示值为 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 似乎无法始终跟踪这些计数器。有没有人能够看到记录这些计数器指标的错误或更好的方法?

4

1 回答 1

3

我能猜到的唯一原因是并发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) ;
  // ...
}
于 2019-05-28T16:11:50.313 回答