'How to check cache hits/misses with jsonapi-rails

Currently using jsonapi-rails to render serialized objects while utilizing some isolated cache.

JSON.generate JSONAPI::Rails::SuccessRenderer.new.render(
  all_data,
    {
      include: %w(attr_1 attr_2),
      meta: {
        total: all_data.size
      },
      expose: {
        url_helpers: ::Rails.application.routes.url_helpers,
        language: language,
      },
      cache: SerializedObjectsCache.instance
    },
  controller
)
# SerializedObjectsCache
def self.instance
    @instance ||=
      begin
        cache = ActiveSupport::Cache::RedisCacheStore.new(
          redis: Redis.current,
          compress: COMPRESS,
          namespace: 'serialized_objects',
          expires_in: EXPIRES_IN
        )
        new(cache)
      end
  end

What I'm trying to figure out is how often we're missing/hitting the cache. Each serialized object has a jsonapi_cache_key method to return a unique key for each object but I'm unsure of how to see the cache hit/miss rate.



Solution 1:[1]

Just a suggestion, I'm not 100% sure I understand your goals here.

You code uses ActiveSupport::Cache::RedisCacheStore, which is instrumented. To be more precise, it publishes cache_read_multi.active_support notification when one calls read_multi (fetch_multi that renderer calls does that under the hood). The notification payload includes hits data (quite dirty rudimentary example):

pry(main)> c = ActiveSupport::Cache::RedisCacheStore.new
pry(main)> ActiveSupport::Notifications.subscribe("cache_read_multi.active_support") { |_, _, _, _, p| puts p.inspect }
pry(main)> c.fetch_multi(:foo) { "default foo" }
"cache_read_multi.active_support"
["cache_read_multi.active_support", "2022-02-03T13:34:12.522+01:00", "2022-02-03T13:34:12.531+01:00", "c4372c000b2f8d1dc867", {:key=>[:foo], :namespace=>nil, :compress=>true, :compress_threshold=>1024, :expires_in=>nil, :race_condition_ttl=>nil, :hits=>[:foo], :super_operation=>:fetch_multi}]
{:key=>[:foo], :namespace=>nil, :compress=>true, :compress_threshold=>1024, :expires_in=>nil, :race_condition_ttl=>nil, :hits=>[:foo], :super_operation=>:fetch_multi}
=> {:foo=>"default foo"}

So, having hits at hand you should be able to calculate the miss/hit rate - but some additional boilerplate is required to aggregate the data for a certain period.

The biggest gotcha here is that adding this additional machinery to accumulate hits stats might kill the performance gains from the caching itself.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Konstantin Strukov