Прометей Счетчик Несоответствие
Я использую простой клиент 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) ;
// ...
}