Reputation: 11
I'm using the Prometheus Java simpleclient within a web service to keep track of how many events result in one status or another.
I'm able to check within the logs that the counter is being invoked and is incrementing internally, but it seems that a lot of times the data is not making it to the /metrics endpoint.
For example, just now, after incrementing the counter 3 times for the same status a few minutes apart each, the log would print out "Current Value = 0, New value = 1" three times. The first two times did not show any data on the /metrics endpoint, and after the 3rd increment, it finally showed a value of 1, which means I lost the record of the first 2 events.
The code I have is the following below, besides some name changes.
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());
}
I'm at a loss as for why Prometheus doesn't seem to be able to keep track of these counters consistently. Is anyone able to see what's wrong or a better way to record these Counter metrics?
Upvotes: 1
Views: 3231
Reputation: 4245
The only reason I can guess are concurrent incrementCounter
calls.
The io.prometheus.client.SimpleCollector#labels
method is not thread-safe (despite that children
field has ConcurrentMap
type), thus it is possible to get different io.prometheus.client.Counter.Child
on every call.
As for getting metrics via http - every call to /metrics
endpoint leads to io.prometheus.client.Counter#collect
method call, which retrieves value of the only one child.
I would suggest you to use your own concurrent map to store counters:
private static final ConcurrentMap<String, Counter.Child> counters = new ConcurrentHashMap<>();
// ...
private static void incrementCounter(String status) {
Counter.Child counter = counters.computeIfAbsent(status, myCounter::labels) ;
// ...
}
Upvotes: 3