Skip to content

Commit a590003

Browse files
committed
Support for TransactionAwareCacheDecorator
This commit makes sure to unwrap any transaction aware cache before collecting metrics for them. Closes gh-8984
1 parent b73e1d4 commit a590003

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/CachePublicMetrics.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
import org.springframework.boot.actuate.metrics.Metric;
2828
import org.springframework.cache.Cache;
2929
import org.springframework.cache.CacheManager;
30+
import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
3031
import org.springframework.core.ResolvableType;
32+
import org.springframework.util.ClassUtils;
3133
import org.springframework.util.LinkedMultiValueMap;
3234
import org.springframework.util.MultiValueMap;
3335

@@ -87,7 +89,7 @@ private void addMetrics(Collection<Metric<?>> metrics, String cacheName,
8789
List<CacheManagerBean> cacheManagerBeans) {
8890
for (CacheManagerBean cacheManagerBean : cacheManagerBeans) {
8991
CacheManager cacheManager = cacheManagerBean.getCacheManager();
90-
Cache cache = cacheManager.getCache(cacheName);
92+
Cache cache = unwrapIfNecessary(cacheManager.getCache(cacheName));
9193
CacheStatistics statistics = getCacheStatistics(cache, cacheManager);
9294
if (statistics != null) {
9395
String prefix = cacheName;
@@ -100,6 +102,14 @@ private void addMetrics(Collection<Metric<?>> metrics, String cacheName,
100102
}
101103
}
102104

105+
private Cache unwrapIfNecessary(Cache cache) {
106+
if (ClassUtils.isPresent("org.springframework.cache.transaction.TransactionAwareCacheDecorator",
107+
getClass().getClassLoader())) {
108+
return TransactionAwareCacheDecoratorHandler.unwrapIfNecessary(cache);
109+
}
110+
return cache;
111+
}
112+
103113
@SuppressWarnings({ "rawtypes", "unchecked" })
104114
private CacheStatistics getCacheStatistics(Cache cache, CacheManager cacheManager) {
105115
if (this.statisticsProviders != null) {
@@ -140,4 +150,19 @@ public CacheManager getCacheManager() {
140150

141151
}
142152

153+
private static class TransactionAwareCacheDecoratorHandler {
154+
155+
private static Cache unwrapIfNecessary(Cache cache) {
156+
try {
157+
if (cache instanceof TransactionAwareCacheDecorator) {
158+
return ((TransactionAwareCacheDecorator) cache).getTargetCache();
159+
}
160+
}
161+
catch (NoClassDefFoundError ex) {
162+
// Ignore
163+
}
164+
return cache;
165+
}
166+
}
167+
143168
}

spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/CachePublicMetricsTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.Arrays;
2020
import java.util.Collection;
21+
import java.util.Collections;
2122
import java.util.HashMap;
2223
import java.util.Map;
2324

@@ -29,7 +30,10 @@
2930
import org.springframework.boot.actuate.cache.ConcurrentMapCacheStatisticsProvider;
3031
import org.springframework.boot.actuate.metrics.Metric;
3132
import org.springframework.cache.CacheManager;
33+
import org.springframework.cache.concurrent.ConcurrentMapCache;
3234
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
35+
import org.springframework.cache.support.SimpleCacheManager;
36+
import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
3337

3438
import static org.assertj.core.api.Assertions.assertThat;
3539
import static org.assertj.core.api.Assertions.entry;
@@ -78,6 +82,19 @@ public void cacheMetricsWithMultipleCacheManagers() {
7882
entry("cache.anotherCacheManager_foo.size", 0L));
7983
}
8084

85+
@Test
86+
public void cacheMetricsWithTransactionAwareCacheDecorator() {
87+
SimpleCacheManager cacheManager = new SimpleCacheManager();
88+
cacheManager.setCaches(Collections.singletonList(
89+
new TransactionAwareCacheDecorator(new ConcurrentMapCache("foo"))));
90+
cacheManager.afterPropertiesSet();
91+
this.cacheManagers.put("cacheManager", cacheManager);
92+
CachePublicMetrics cpm = new CachePublicMetrics(this.cacheManagers,
93+
providers(new ConcurrentMapCacheStatisticsProvider()));
94+
Map<String, Number> metrics = metrics(cpm);
95+
assertThat(metrics).containsOnly(entry("cache.foo.size", 0L));
96+
}
97+
8198
private Map<String, Number> metrics(CachePublicMetrics cpm) {
8299
Collection<Metric<?>> metrics = cpm.metrics();
83100
assertThat(metrics).isNotNull();

0 commit comments

Comments
 (0)