Is io.prometheus.client.Gauge can be used for thread safety counters

4.5k views Asked by At

I am using io.prometheus.client.Gauge to implement a thread safety counter to calculate the number of events processed in a time frame. Now there are several threads that are processing the events. And all can update the counter when it finishes the processing. My question ins is Gauge counters are thread safety in nature? Following is my implementation.

    private Map<String, Gauge> gaugeMap = new ConcurrentHashMap<>();
    
    // This method will be called to register the Gauge
    private void registerCounter(String metricName) {
        Gauge gauge = Gauge.build()
                .name(metricName)
                .help(metricName)
                .register(meterRegistry.getPrometheusRegistry());
        gaugeMap.put(metricName, gauge);
    }
    
    public void incrementCounter(String metricName) {
        if (isCounterPresent(metricName)) {
            gaugeMap.get(metricName).inc();
        }
    }
   public void incrementCounter(String metricName, long value) {
        if (isCounterPresent(metricName)) {
            gaugeMap.get(metricName).inc(value);
        }
    }

Following is my client code.

// on application startup I am calling registerCounter for all metrics
@PostConstruct
private void registerMetrics(List<String> metricList) {
    // for each of metricList --> call registerCounter(String metricName)
}


Thread1
-------------------
// process N events
// call incrementCounter("metric-1", N);

Thread2
-------------------
// process N events
// call incrementCounter("metric-1", N);

Thread3
-------------------
// process N events
// call incrementCounter("metric-1", N);

Now my question is as multiple threads are incrementing the same counter, then will it give me the correct value?

2

There are 2 answers

0
Anar Sultanov On

Prometheus JVM Client README states that:

the default inc(), dec() and set() methods on Gauge take care of thread safety

0
Yury Vasyutinskiy On

The gauge is thread safe and uses CAS operation to support non-blocking state update. All the metric collectors are. In the end they has to be exposed by the endpoint in separate thread. Hence the state should be consistent for read and writes. One particular thing to keep in mind is that the higher is contention the lower is efficiency of CAS operation. So make sure you don't expose it for tens of threads that are trying to update it at the same time.

Secondly, using gauge as counter is not a good idea as there is a special type for that - Counter. Some Prometheus functions are specifically implemented and optimized to be used for counters - rate, irate etc. So in case you need to collect and expose the number of events processed by several threads the recommendation is to use Counter.