Прометей Счетчик Несоответствие

Я использую простой клиент Prometheus Java в веб-сервисе, чтобы отслеживать, сколько событий приводит к тому или иному состоянию.

Я могу проверить в журналах, что счетчик вызывается и увеличивается на внутреннем уровне, но кажется, что часто данные не попадают в конечную точку /metrics.

Например, только сейчас, после увеличения счетчика 3 раза для одного и того же состояния с интервалом в несколько минут каждый, журнал будет распечатывать "Текущее значение = 0, Новое значение = 1" три раза. Первые два раза не показывали никаких данных в конечной точке /metrics, и после 3-го приращения оно наконец показало значение 1, что означает, что я потерял запись первых двух событий.

У меня есть следующий код, кроме некоторых изменений имени.

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());
}

Я в недоумении, почему Прометей, похоже, не в состоянии последовательно отслеживать эти счетчики. Кто-нибудь может увидеть, что не так или лучший способ записать эти метрики счетчика?

1 ответ

Единственная причина, по которой я могу догадаться - это одновременность 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) ;
  // ...
}
Другие вопросы по тегам