All Downloads are FREE. Search and download functionalities are using the official Maven repository.

no.nav.common.kafka.consumer.util.TopicConsumerMetrics Maven / Gradle / Ivy

package no.nav.common.kafka.consumer.util;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import no.nav.common.kafka.consumer.ConsumeStatus;
import org.apache.kafka.clients.consumer.ConsumerRecord;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Consumer listener which adds a consumption status metric for each topic + partition
 * @param  topic key
 * @param  topic value
 */
public class TopicConsumerMetrics implements TopicConsumerListener {

    public final static String KAFKA_CONSUMER_STATUS_COUNTER = "kafka_consumer_status";

    public final static String KAFKA_CONSUMER_CONSUMED_OFFSET_GAUGE = "kafka_consumer_consumed_offset";

    private final MeterRegistry meterRegistry;

    private final Map statusCounterMap = new ConcurrentHashMap<>();

    private final Map consumedOffsetGaugeMap = new ConcurrentHashMap<>();

    private final Map consumedOffsetMap = new ConcurrentHashMap<>();

    public TopicConsumerMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @Override
    public void onConsumed(ConsumerRecord record, ConsumeStatus status) {
        String statusMapKey = String.format("%s-%d-%s", record.topic(), record.partition(), status);

        statusCounterMap.computeIfAbsent(statusMapKey, (k) ->
                Counter.builder(KAFKA_CONSUMER_STATUS_COUNTER)
                        .tag("topic", record.topic())
                        .tag("partition", String.valueOf(record.partition()))
                        .tag("status", status.name().toLowerCase())
                        .register(meterRegistry))
                .increment();

        if (status == ConsumeStatus.OK) {
            String offsetMapKey = String.format("%s-%d", record.topic(), record.partition());

            consumedOffsetMap.put(offsetMapKey, record.offset());

            consumedOffsetGaugeMap.computeIfAbsent(statusMapKey, (k) ->
                    Gauge.builder(KAFKA_CONSUMER_CONSUMED_OFFSET_GAUGE, () -> {
                        Long offset = consumedOffsetMap.get(offsetMapKey);
                        return offset != null ? offset : 0;
                    })
                    .description("The latest consumed offset. The offset is not guaranteed to have been committed.")
                    .tag("topic", record.topic())
                    .tag("partition", String.valueOf(record.partition()))
                    .register(meterRegistry));
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy