blob: 10234e879f5dfd944dd64dba52a51c8bbeab4611 [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.math.BigDecimal;
import java.math.MathContext;
import java.util.concurrent.TimeUnit;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
import org.apache.jackrabbit.oak.api.jmx.ConsolidatedCacheStatsMBean;
import org.apache.jackrabbit.oak.api.jmx.PersistentCacheStatsMBean;
import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
import org.apache.jackrabbit.oak.spi.whiteboard.Tracker;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import static org.apache.jackrabbit.oak.cache.CacheStats.timeInWords;
import static org.apache.jackrabbit.oak.commons.IOUtils.humanReadableByteCount;
import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
@Component(service = {})
public class ConsolidatedCacheStats implements ConsolidatedCacheStatsMBean {
private Tracker<CacheStatsMBean> cacheStats;
private Tracker<PersistentCacheStatsMBean> persistentCacheStats;
private Registration mbeanReg;
@Override
public TabularData getCacheStats() {
TabularDataSupport tds;
try {
TabularType tt = new TabularType(CacheStatsData.class.getName(),
"Consolidated Cache Stats", CacheStatsData.TYPE, new String[]{"name"});
tds = new TabularDataSupport(tt);
for(CacheStatsMBean stats : cacheStats.getServices()){
tds.put(new CacheStatsData(stats).toCompositeData());
}
for(CacheStatsMBean stats : persistentCacheStats.getServices()){
tds.put(new CacheStatsData(stats).toCompositeData());
}
} catch (OpenDataException e) {
throw new IllegalStateException(e);
}
return tds;
}
@Activate
private void activate(BundleContext context){
Whiteboard wb = new OsgiWhiteboard(context);
cacheStats = wb.track(CacheStatsMBean.class);
persistentCacheStats = wb.track(PersistentCacheStatsMBean.class);
mbeanReg = registerMBean(wb,
ConsolidatedCacheStatsMBean.class,
this,
ConsolidatedCacheStatsMBean.TYPE,
"Consolidated Cache statistics");
}
@Deactivate
private void deactivate(){
if(mbeanReg != null){
mbeanReg.unregister();
}
if(cacheStats != null){
cacheStats.stop();
}
if(persistentCacheStats != null) {
persistentCacheStats.stop();
}
}
private static class CacheStatsData {
static final String[] FIELD_NAMES = new String[]{
"name",
"requestCount",
"hitCount",
"hitRate",
"missCount",
"missRate",
"loadCount",
"loadSuccessCount",
"loadExceptionCount",
"totalLoadTime",
"averageLoadPenalty",
"evictionCount",
"elementCount",
"totalWeight",
"maxWeight",
};
static final String[] FIELD_DESCRIPTIONS = FIELD_NAMES;
@SuppressWarnings("rawtypes")
static final OpenType[] FIELD_TYPES = new OpenType[]{
SimpleType.STRING,
SimpleType.LONG,
SimpleType.LONG,
SimpleType.BIGDECIMAL,
SimpleType.LONG,
SimpleType.BIGDECIMAL,
SimpleType.LONG,
SimpleType.LONG,
SimpleType.LONG,
SimpleType.STRING,
SimpleType.STRING,
SimpleType.LONG,
SimpleType.LONG,
SimpleType.STRING,
SimpleType.STRING,
};
static final CompositeType TYPE = createCompositeType();
static CompositeType createCompositeType() {
try {
return new CompositeType(
CacheStatsData.class.getName(),
"Composite data type for Cache statistics",
CacheStatsData.FIELD_NAMES,
CacheStatsData.FIELD_DESCRIPTIONS,
CacheStatsData.FIELD_TYPES);
} catch (OpenDataException e) {
throw new IllegalStateException(e);
}
}
private final CacheStatsMBean stats;
public CacheStatsData(CacheStatsMBean stats){
this.stats = stats;
}
CompositeDataSupport toCompositeData() {
Object[] values = new Object[]{
stats.getName(),
stats.getRequestCount(),
stats.getHitCount(),
new BigDecimal(stats.getHitRate(),new MathContext(2)),
stats.getMissCount(),
new BigDecimal(stats.getMissRate(), new MathContext(2)),
stats.getLoadCount(),
stats.getLoadSuccessCount(),
stats.getLoadExceptionCount(),
timeInWords(stats.getTotalLoadTime()),
TimeUnit.NANOSECONDS.toMillis((long) stats.getAverageLoadPenalty()) + "ms",
stats.getEvictionCount(),
stats.getElementCount(),
humanReadableByteCount(stats.estimateCurrentWeight()),
humanReadableByteCount(stats.getMaxTotalWeight()),
};
try {
return new CompositeDataSupport(TYPE, FIELD_NAMES, values);
} catch (OpenDataException e) {
throw new IllegalStateException(e);
}
}
}
}