Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[prometheus-metrics-instrumentation-caffeine] Cannot register multiple Caffeine cache #1174

@kaustubhDsarathi

Description

@kaustubhDsarathi

Context:
I'm using prometheus-metrics-instrumentation-caffeine to instrument my caffeine cache.

public class UserCache {

    public static final String KEY_REMOVED_FROM_CACHE = "key={} removed from cache";
    @Getter
    private LoadingCache<String, Optional<UserDetailDto>> cache1;
    private LoadingCache<String, Optional<UserDetailDto>> cache2;
    @Getter
    private LoadingCache<String, Optional<UserDetailDto>> cache3;
    private final UserRepository userRepository;
    private final CacheConfig cacheConfig;
    private final PrometheusMeterRegistry prometheusMeterRegistry;

    @PostConstruct
    void init() {
        if(cacheConfig.isEnabled()) {
            ExecutorService threadPool = Executors.newFixedThreadPool(4);
            cache1 = Caffeine.newBuilder()
                    .maximumSize(100_000) // 100_000 test-user data will be cached.
                    .removalListener(TestCache::onRemoval)
                    .refreshAfterWrite(2, TimeUnit.HOURS)
                    .executor(threadPool)
                    .recordStats()
                   .build(userRepository::loadCache1);

            cache2 = Caffeine.newBuilder()
                    .maximumSize(5_000) // 5000 test-user data will be cached.
                    .removalListener(TestCache::onRemoval)
                    .refreshAfterWrite(5, TimeUnit.HOURS) // refresh cache after 5 hours write
                    .executor(threadPool)
                    .build(userRepository::loadCache2);


            cache3 = Caffeine.newBuilder()
                    .maximumSize(100_000) // 100_000 test-user data will be cached.
                    .removalListener(TestCache::onRemoval)
                    .refreshAfterWrite(1, TimeUnit.HOURS)
                    .executor(threadPool)
                    .build(userRepository::loadCache3);

            CacheMetricsCollector collector = new CacheMetricsCollector();
            collector.addCache("cache1", cache1);
            collector.addCache("cache2", cache2);
            collector.addCache("cache3", cache3);

            prometheusMeterRegistry.getPrometheusRegistry().register(collector);
        }

    private static void onRemoval(@Nullable Object key, @Nullable Object value, RemovalCause cause) {
        log.atDebug().log(KEY_REMOVED_FROM_CACHE, key);
    }
}

After running the application and accessing the metrics, I'm getting the following error
caffeine_cache_estimated_size: duplicate metric name.
image
image
image

There is no mention in the Javadoc whether we can provide different names to the collector also the register() method seems to be missing in the actual code
image

As a workaround, I'm currently manually registering the Gauge objects in PrometheusMeterRegistry

public void registerCacheMetrics(String cacheName, PrometheusMeterRegistry prometheusMeterRegistry, LoadingCache<?, ?> loadingCache) {

        // Register custom gauges for cache metrics
        Gauge.builder(cacheName + ".hit.count", loadingCache, cache -> cache.stats().hitCount())
                .description("Number of cache hits")
                .register(prometheusMeterRegistry);

        Gauge.builder(cacheName + ".miss.count", loadingCache, cache -> cache.stats().missCount())
                .description("Number of cache misses")
                .register(prometheusMeterRegistry);

        Gauge.builder(cacheName + ".requests.count", loadingCache, cache -> cache.stats().requestCount())
                .description("Number of times cache requested")
                .register(prometheusMeterRegistry);

        Gauge.builder(cacheName + ".eviction.count", loadingCache, cache -> cache.stats().evictionCount())
                .description("Number of cache evictions")
                .register(prometheusMeterRegistry);

        Gauge.builder(cacheName + ".load.success.count", loadingCache, cache -> cache.stats().loadSuccessCount())
                .description("Number of successful cache loads")
                .register(prometheusMeterRegistry);

        Gauge.builder(cacheName + ".load.failure.count", loadingCache, cache -> cache.stats().loadFailureCount())
                .description("Number of cache load failures")
                .register(prometheusMeterRegistry);

        Gauge.builder(cacheName + ".load.total", loadingCache, cache -> cache.stats().totalLoadTime())
                .description("Time taken to load cache")
                .register(prometheusMeterRegistry);
    }

Is there a way we can instrument multiple Cache objects using CacheMetricsCollector?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions