Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache abstraction does not log hit / miss for synchronized access #25248

Closed
elab opened this issue Jun 13, 2020 · 4 comments
Closed

Cache abstraction does not log hit / miss for synchronized access #25248

elab opened this issue Jun 13, 2020 · 4 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@elab
Copy link

elab commented Jun 13, 2020

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:

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?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jun 13, 2020
@elab elab changed the title Cache abstraction: log hit / miss for synchronized contexts Cache abstraction: log hit / miss for synchronized contexts (patch included) Jun 13, 2020
@elab
Copy link
Author

elab commented Sep 1, 2020

Hi, is there any news on this issue?
We would like to switch to Spring's declarative caching control (@Cacheable annotation, synchronized) , but currently blocked by this issue, as we are required to log hits and misses.

@snicoll snicoll added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Sep 1, 2020
@snicoll snicoll modified the milestones: 5.3 RC1, 5.2.9 Sep 1, 2020
@jhoeller jhoeller added in: core Issues in core modules (aop, beans, core, context, expression) in: messaging Issues in messaging modules (jms, messaging) and removed in: messaging Issues in messaging modules (jms, messaging) labels Sep 1, 2020
@snicoll snicoll changed the title Cache abstraction: log hit / miss for synchronized contexts (patch included) Cache abstraction dos not log hit / miss for synchronized access Sep 2, 2020
@snicoll snicoll changed the title Cache abstraction dos not log hit / miss for synchronized access Cache abstraction does not log hit / miss for synchronized access Sep 2, 2020
@snicoll snicoll closed this as completed in cdfdc34 Sep 2, 2020
@snicoll
Copy link
Member

snicoll commented Sep 2, 2020

Thanks for the report and the suggestion. This is fixed in the upcoming 5.2.9 and 5.3.0.RC1. Feel free to give 5.2.9.BUILD-SNAPSHOT a try from https://repo.spring.io/snapshot. A new snapshot with the fix should be available in a few minutes.

@xenoterracide
Copy link

reading your patch... this was only fixed for synchronized? why not unsynchronized? why is it not for everything? I'm trying to figure out if I'm getting cache hits (seems to be misses), nothing is being logged for calls to this this method... even though I'm definitely calling it, it does seem to have cache misses.

2022-10-17 12:09:07.172 TRACE 77112 --- [  restartedMain] o.s.c.a.AnnotationCacheOperationSource   : Adding cacheable method 'findAll' with attribute: [Builder[public java.util.List com.capitalone.e1.domain.core.dmsr.BusinessDivisionRepository.findAll()] caches=[book-divisions] | key='' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false']

just using simple cache per the reference docs as I have not configured anything regarding the cache starter.

spring.cache.cache-names=book-divisions
spring.cache.caffeine.spec=maximumSize=1000,expireAfterAccess=60s

@xenoterracide
Copy link

worth mentioning if the log isn't saying it that method has no arguments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

5 participants