| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.apache.jackrabbit.oak.cache.impl; |
| |
| import java.util.List; |
| import java.util.Map; |
| |
| import com.codahale.metrics.Counter; |
| import com.codahale.metrics.Metric; |
| import com.codahale.metrics.MetricRegistry; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Maps; |
| |
| import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean; |
| import org.osgi.service.component.annotations.Component; |
| import org.osgi.service.component.annotations.Reference; |
| import org.osgi.service.component.annotations.ReferenceCardinality; |
| import org.osgi.service.component.annotations.ReferencePolicy; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * An OSGi component that binds to all {@link CacheStatsMBean} instances and |
| * exposes their counters as {@link Metric}s. |
| */ |
| @Component(immediate = true) |
| public class CacheStatsMetrics { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(CacheStatsMetrics.class); |
| |
| static final String REQUEST = "request"; |
| static final String HIT = "hit"; |
| static final String MISS = "miss"; |
| static final String EVICTION = "eviction"; |
| static final String ELEMENT = "element"; |
| static final String LOAD_TIME = "loadTime"; |
| |
| private static final List<String> TYPES = ImmutableList.of( |
| REQUEST, HIT, MISS, EVICTION, ELEMENT, LOAD_TIME); |
| |
| private Map<String, CacheStatsMBean> cacheStatsMBeans = Maps.newHashMap(); |
| private MetricRegistry registry = new MetricRegistry(); |
| |
| @Reference( |
| cardinality = ReferenceCardinality.AT_LEAST_ONE, |
| policy = ReferencePolicy.DYNAMIC |
| ) |
| synchronized void addCacheStatsMBean(CacheStatsMBean stats) { |
| LOG.debug("addCacheStatsMBean({})", stats.getName()); |
| cacheStatsMBeans.put(stats.getName(), stats); |
| registerCacheStatsMBean(this.registry, stats); |
| } |
| |
| synchronized void removeCacheStatsMBean(CacheStatsMBean stats) { |
| LOG.debug("removeCacheStatsMBean({})", stats.getName()); |
| cacheStatsMBeans.remove(stats.getName()); |
| unregisterCacheStatsMBean(this.registry, stats); |
| } |
| |
| @Reference( |
| target = "(name=oak)" |
| ) |
| synchronized void setMetricRegistry(MetricRegistry registry) { |
| LOG.debug("setMetricRegistry({})", registry); |
| for (CacheStatsMBean stats : cacheStatsMBeans.values()) { |
| unregisterCacheStatsMBean(this.registry, stats); |
| registerCacheStatsMBean(registry, stats); |
| } |
| this.registry = registry; |
| } |
| |
| private static void registerCacheStatsMBean(MetricRegistry registry, |
| CacheStatsMBean stats) { |
| registerMetric(registry, new RequestCounter(stats)); |
| registerMetric(registry, new HitCounter(stats)); |
| registerMetric(registry, new MissCounter(stats)); |
| registerMetric(registry, new EvictionCounter(stats)); |
| registerMetric(registry, new ElementCounter(stats)); |
| registerMetric(registry, new LoadTimeCounter(stats)); |
| } |
| |
| private static void registerMetric(MetricRegistry registry, |
| CacheStatsMBeanCounter metric) { |
| String name = metric.getName(); |
| registry.remove(name); |
| registry.register(name, metric); |
| } |
| |
| private static void unregisterCacheStatsMBean(MetricRegistry registry, |
| CacheStatsMBean stats) { |
| String name = stats.getName(); |
| for (String t : TYPES) { |
| registry.remove(metricName(name, t)); |
| } |
| } |
| |
| static String metricName(String cacheStatsName, String type) { |
| return "CacheStats." + cacheStatsName + "." + type; |
| } |
| |
| private abstract static class CacheStatsMBeanCounter |
| extends Counter { |
| |
| protected CacheStatsMBean stats; |
| protected String type; |
| |
| CacheStatsMBeanCounter(CacheStatsMBean stats, String type) { |
| this.stats = stats; |
| this.type = type; |
| } |
| |
| String getName() { |
| return metricName(stats.getName(), type); |
| } |
| } |
| |
| private static final class RequestCounter extends CacheStatsMBeanCounter { |
| |
| RequestCounter(CacheStatsMBean stats) { |
| super(stats, REQUEST); |
| } |
| |
| @Override |
| public long getCount() { |
| return stats.getRequestCount(); |
| } |
| } |
| |
| private static final class HitCounter extends CacheStatsMBeanCounter { |
| |
| HitCounter(CacheStatsMBean stats) { |
| super(stats, HIT); |
| } |
| |
| @Override |
| public long getCount() { |
| return stats.getHitCount(); |
| } |
| } |
| |
| private static final class MissCounter extends CacheStatsMBeanCounter { |
| |
| MissCounter(CacheStatsMBean stats) { |
| super(stats, MISS); |
| } |
| |
| @Override |
| public long getCount() { |
| return stats.getMissCount(); |
| } |
| } |
| |
| private static final class EvictionCounter extends CacheStatsMBeanCounter { |
| |
| EvictionCounter(CacheStatsMBean stats) { |
| super(stats, EVICTION); |
| } |
| |
| @Override |
| public long getCount() { |
| return stats.getEvictionCount(); |
| } |
| } |
| |
| private static final class ElementCounter extends CacheStatsMBeanCounter { |
| |
| ElementCounter(CacheStatsMBean stats) { |
| super(stats, ELEMENT); |
| } |
| |
| @Override |
| public long getCount() { |
| return stats.getElementCount(); |
| } |
| } |
| |
| private static final class LoadTimeCounter extends CacheStatsMBeanCounter { |
| |
| LoadTimeCounter(CacheStatsMBean stats) { |
| super(stats, LOAD_TIME); |
| } |
| |
| @Override |
| public long getCount() { |
| return stats.getTotalLoadTime(); |
| } |
| } |
| } |