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

Add CacheErrorHandler implementation that logs exceptions rather than rethrowing them #27826

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.cache.interceptor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.cache.Cache;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
* A {@link CacheErrorHandler} implementation that simply logs error message.
*
* @author Adam Ostrožlík
* @since 5.3
*/
public final class LoggingCacheErrorHandler implements CacheErrorHandler {

private final Log logger;
private final boolean includeStacktrace;

/**
* Construct new {@link LoggingCacheErrorHandler} that may log stacktraces.
* @param includeStacktrace whether to log or not log stacktraces.
* @param logger custom logger.
*/
private LoggingCacheErrorHandler(boolean includeStacktrace, Log logger) {
Assert.notNull(logger, "logger cannot be null");
this.includeStacktrace = includeStacktrace;
this.logger = logger;
}

@Override
public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
logCacheError("Cache '" + cache.getName() + "' failed to get entry with key '" + key + "'", exception);
}

@Override
public void handleCachePutError(RuntimeException exception, Cache cache, Object key, @Nullable Object value) {
logCacheError("Cache '" + cache.getName() + "' failed to put entry with key '" + key + "'", exception);
}

@Override
public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
logCacheError("Cache '" + cache.getName() + "' failed to evict entry with key '" + key + "'", exception);
}

@Override
public void handleCacheClearError(RuntimeException exception, Cache cache) {
logCacheError("Cache '" + cache.getName() + "' failed to clear itself", exception);
}

private void logCacheError(String msg, RuntimeException ex) {
if (this.includeStacktrace) {
logger.warn(msg, ex);
}
else {
logger.warn(msg);
}
}

/**
* Builder class for {@link LoggingCacheErrorHandler}.
*/
public static class Builder {
private Log logger;
private boolean includeStacktrace;

/**
* Overrides default logger.
* @param logger new logger.
* @return this builder.
*/
public Builder setLogger(Log logger) {
this.logger = logger;
return this;
}

/**
* Enable/disable logging of stacktraces.
* @param includeStacktrace true - include stacktraces; false otherwise.
* @return this builder.
*/
public Builder setIncludeStacktrace(boolean includeStacktrace) {
this.includeStacktrace = includeStacktrace;
return this;
}

public LoggingCacheErrorHandler build() {
if (logger == null) {
return new LoggingCacheErrorHandler(this.includeStacktrace, LogFactory.getLog(LoggingCacheErrorHandler.class));
}
return new LoggingCacheErrorHandler(this.includeStacktrace, logger);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.cache.interceptor;

import org.apache.commons.logging.Log;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cache.support.NoOpCache;

import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

/**
* Tests for {@link LoggingCacheErrorHandler}.
*
* @author Adam Ostrožlík
*/
@ExtendWith(MockitoExtension.class)
public class LoggingCacheErrorHandlerTests {

@Mock
Log logger;

@Test
void givenHandlerWhenHandleGetErrorThenLogWithoutException() {
LoggingCacheErrorHandler handler = new LoggingCacheErrorHandler.Builder()
.setLogger(logger)
.build();
handler.handleCacheGetError(new RuntimeException(), new NoOpCache("NOOP"), "key");
verify(logger, times(1)).warn(anyString());
}

@Test
void givenHandlerWhenHandleGetErrorThenLogWithException() {
LoggingCacheErrorHandler handler = new LoggingCacheErrorHandler.Builder()
.setLogger(logger)
.setIncludeStacktrace(true)
.build();
RuntimeException exception = new RuntimeException();
handler.handleCacheGetError(exception, new NoOpCache("NOOP"), "key");
verify(logger, times(1)).warn(anyString(), eq(exception));
}

}