-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Description
General logging of hit / miss has been added in #16277.
For synchronized cache contexts (@Cacheable(sync=true)
), no logging happens yet.
It's also not that straightforward, since in that case the mapping function will be passed directly to the Cache implementation (e.g. Caffeine) and Spring has no knowledge about if the mapper function has been called or if the returned value has been retrieved from the cache.
What we can do? I would propose to decorate the mapping function with an "invoked" flag (which will tell if the function has been invoked by the cache implementation) and with a logging for the "miss" case. The logging directly inside the function is necessary because we want to log misses before invocation of the underlying mapper function. The flag "invoked" is necessary to recognize the "hit" case (we can only definitely say that after the value has been returned from the cache implementation).
Here is the place in the code:
Lines 377 to 384 in 1279b3b
if (contexts.isSynchronized()) { | |
CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next(); | |
if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) { | |
Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT); | |
Cache cache = context.getCaches().iterator().next(); | |
try { | |
return wrapCacheValue(method, cache.get(key, () -> unwrapReturnValue(invokeOperation(invoker)))); | |
} |
The line return wrapCacheValue(method, cache.get(key, () -> unwrapReturnValue(invokeOperation(invoker))));
could be changed to something like that:
boolean[] invoked = new boolean[1];
Object returnValue = wrapCacheValue(method, cache.get(key, () -> {
invoked[0] = true; // cache miss; log "miss" *before* calling the underlying mapper function
if (logger.isTraceEnabled()) {
logger.trace("No cache entry for key '" + key + "' in cache " + cache.getName());
}
unwrapReturnValue(invokeOperation(invoker)));
});
if (!invoked[0]) { // cache hit; log "hit" after retrieving the value from the cache
if (logger.isTraceEnabled()) {
logger.trace("Cache entry for key '" + key + "' found in cache '" + cache.getName() + "'");
}
}
return returnValue;
What do you think? Perhaps any easier solution possible?