blob: b5ea2445125539c4bde6cdfd55375feb4a2d6cdb [file] [log] [blame]
/*
* 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();
}
}
}