/*
* Copyright 2012-2017 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
*
* http://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.boot.actuate.endpoint;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.springframework.boot.actuate.cache.CacheStatistics;
import org.springframework.boot.actuate.cache.CacheStatisticsProvider;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.core.ResolvableType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
/**
* A {@link PublicMetrics} implementation that provides cache statistics.
*
* @author Stephane Nicoll
* @since 1.3.0
*/
public class CachePublicMetrics implements PublicMetrics {
private final Map<String, CacheManager> cacheManagers;
private final Collection<CacheStatisticsProvider<?>> statisticsProviders;
/**
* Create a new {@link CachePublicMetrics} instance.
* @param cacheManagers the cache managers
* @param statisticsProviders the statistics providers
*/
public CachePublicMetrics(Map<String, CacheManager> cacheManagers,
Collection<CacheStatisticsProvider<?>> statisticsProviders) {
this.cacheManagers = cacheManagers;
this.statisticsProviders = statisticsProviders;
}
@Override
public Collection<Metric<?>> metrics() {
Collection<Metric<?>> metrics = new HashSet<>();
for (Map.Entry<String, List<CacheManagerBean>> entry : getCacheManagerBeans()
.entrySet()) {
addMetrics(metrics, entry.getKey(), entry.getValue());
}
return metrics;
}
private MultiValueMap<String, CacheManagerBean> getCacheManagerBeans() {
MultiValueMap<String, CacheManagerBean> cacheManagerNamesByCacheName = new LinkedMultiValueMap<>();
for (Map.Entry<String, CacheManager> entry : this.cacheManagers.entrySet()) {
for (String cacheName : entry.getValue().getCacheNames()) {
cacheManagerNamesByCacheName.add(cacheName,
new CacheManagerBean(entry.getKey(), entry.getValue()));
}
}
return cacheManagerNamesByCacheName;
}
private void addMetrics(Collection<Metric<?>> metrics, String cacheName,
List<CacheManagerBean> cacheManagerBeans) {
for (CacheManagerBean cacheManagerBean : cacheManagerBeans) {
CacheManager cacheManager = cacheManagerBean.getCacheManager();
Cache cache = cacheManager.getCache(cacheName);
CacheStatistics statistics = getCacheStatistics(cache, cacheManager);
if (statistics != null) {
String prefix = cacheName;
if (cacheManagerBeans.size() > 1) {
prefix = cacheManagerBean.getBeanName() + "_" + prefix;
}
prefix = "cache." + prefix + (prefix.endsWith(".") ? "" : ".");
metrics.addAll(statistics.toMetrics(prefix));
}
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private CacheStatistics getCacheStatistics(Cache cache, CacheManager cacheManager) {
if (this.statisticsProviders != null) {
for (CacheStatisticsProvider provider : this.statisticsProviders) {
Class<?> cacheType = ResolvableType
.forClass(CacheStatisticsProvider.class, provider.getClass())
.resolveGeneric();
if (cacheType.isInstance(cache)) {
CacheStatistics statistics = provider.getCacheStatistics(cacheManager,
cache);
if (statistics != null) {
return statistics;
}
}
}
}
return null;
}
private static class CacheManagerBean {
private final String beanName;
private final CacheManager cacheManager;
CacheManagerBean(String beanName, CacheManager cacheManager) {
this.beanName = beanName;
this.cacheManager = cacheManager;
}
public String getBeanName() {
return this.beanName;
}
public CacheManager getCacheManager() {
return this.cacheManager;
}
}
}