Monitoring Guava Cache Statistics


Guava Cache is one of the most extensive in memory caching library for JVM.

Any high throughput application would not only employ distributed cache such as Redis but also in memory local caching.

The applications I have worked on extensively used Guava Cache to serve thousands of requests per seconds.

One of the problems I have faced in the past is monitoring the performance of the local cache itself. For example, the following metrics are very important to monitor for any cache:

  • Hit Rate
  • Miss Rate
  • No. of entries in the cache

In addition, since Guava is a Loading Cache, it is also very important to monitor The time the cache has spent loading new values

That is when I was looking to solution to these problems, I came across that solution is built itself in Guava Cache through recordstats

As per the documentation of recordstats

Enable the accumulation of CacheStats during the operation of the cache. Without this Cache.stats()will return zero for all statistics. Note that recording stats requires bookkeeping to be performed with each operation, and thus imposes a performance penalty on cache operation.

Since there is a performance overhead of this operation, I recommend that you have a feature flag to enable this functionality and turn it off after collecting the performance statistics for any high throughput application in production.

How to enable record stats?

Simply use the recordStats() function while building the cache

 localCache = CacheBuilder
    .newBuilder()
    .expireAfterWrite(2, TimeUnit.SECONDS)
    .refreshAfterWrite(1,
            TimeUnit.SECONDS)
    .maximumSize(5)
    .recordStats()
    .build(new CacheLoader<>() {
        @Override
        public MatchListDO load(Integer key) {
            
        }

        @Override
        public ListenableFuture<Integer> reload(Integer key, MatchListDO oldValue) {
            
        }
    });

How do I visualize the data?

The best way to visualize the Guava cache statistics is through Spring boot Actuator -> Prometheus -> Grafana

First ensure that Spring boot actuator is enabled for your project. It can be done by adding the dependency

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

And adding the relevant properties in the configuration

management:
  metrics:
    export:
      prometheus:
        enabled: true
    enable.jvm: true

    distribution:
      percentiles-histogram:
        http:
          server:
            requests: true

  endpoints:
    web:
      exposure:
        include: health, prometheus, loggers, metrics, scheduledtasks, threaddump, info

Then, we enable prometheus monitoring in our application, by adding the micrometer dependency

<dependency>
	<groupId>io.micrometer</groupId>
	<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

Finally we hookup our cache with micrometer using the GuavaCacheMetrics

 GuavaCacheMetrics.monitor(meterRegistry, localCache, "localCache");

I created a Guava cache monitoring dashboard in Grafana:

I have uploaded this sample application on github along with the Grafana dashboard