170 lines
5.5 KiB
Java
170 lines
5.5 KiB
Java
/*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2017 Ziver Koc
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
package zutil.log;
|
|
|
|
import zutil.ClassUtil;
|
|
|
|
import javax.management.MBeanServer;
|
|
import javax.management.ObjectName;
|
|
import java.lang.management.ManagementFactory;
|
|
import java.util.HashMap;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
/**
|
|
* This class is used for performance measurements on an application.
|
|
* The counter values will be published in JMX and can be viewed in JConsole.
|
|
*/
|
|
public class CounterManager {
|
|
/** a two dimensional map [Class][Counter ID] for storing singleton objects **/
|
|
private static HashMap<String, HashMap<String, Counter>> counters = new HashMap<>();
|
|
|
|
/**
|
|
* @param name a unique name/id of the counter
|
|
* @return a singleton instance of the counter name with the calling class as context. Will always return a valid object.
|
|
*/
|
|
public static Counter getCounter(String name) {
|
|
return getCounter(ClassUtil.getCallingClass(CounterManager.class), name);
|
|
}
|
|
/**
|
|
* @param clazz the counter context
|
|
* @param name a unique name/id of the counter
|
|
* @return a singleton instance of the counter name. Will always return a valid object.
|
|
*/
|
|
public static Counter getCounter(Class clazz, String name) {
|
|
return getCounter(clazz.getName(), name);
|
|
}
|
|
private static synchronized Counter getCounter(String clazz, String name) {
|
|
Counter counter;
|
|
if ( ! counters.containsKey(clazz) || ! counters.get(clazz).containsKey(name)) {
|
|
// Get the platform MBeanServer
|
|
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
|
// Unique identification of MBeans
|
|
counter = new Counter(name);
|
|
|
|
try {
|
|
// Uniquely identify the MBeans and register them with the platform MBeanServer
|
|
ObjectName objectName = new ObjectName(clazz + ":name=" + counter.getName());
|
|
mbs.registerMBean(counter, objectName);
|
|
// Register the singleton
|
|
if ( ! counters.containsKey(clazz))
|
|
counters.put(clazz, new HashMap<String, Counter>());
|
|
counters.get(clazz).put(name, counter);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
else
|
|
counter = counters.get(clazz).get(name);
|
|
return counter;
|
|
}
|
|
|
|
|
|
/**
|
|
* MBean Counter definition for publishing data in JMX
|
|
*/
|
|
public interface CounterMBean {
|
|
String getName();
|
|
|
|
int getValue();
|
|
int getMax();
|
|
int getMin();
|
|
double getAverage();
|
|
}
|
|
|
|
|
|
public static class Counter implements CounterMBean{
|
|
private final String name;
|
|
private int max;
|
|
private int min;
|
|
private double average;
|
|
private int sampleCount;
|
|
private AtomicInteger counter = new AtomicInteger();
|
|
|
|
|
|
protected Counter(String name){
|
|
this.name = name;
|
|
}
|
|
|
|
|
|
public void add(int i){
|
|
int prev = counter.getAndAdd(i);
|
|
updateMetaData(prev + i);
|
|
}
|
|
public void set(int i){
|
|
counter.getAndSet(i);
|
|
updateMetaData(i);
|
|
}
|
|
public void increment(){
|
|
int i = counter.incrementAndGet();
|
|
updateMetaData(i);
|
|
}
|
|
public void decrement(){
|
|
int i = counter.decrementAndGet();
|
|
updateMetaData(i);
|
|
}
|
|
private void updateMetaData(int i){
|
|
if (max < i)
|
|
max = i;
|
|
if (min > i)
|
|
min = i;
|
|
|
|
average = (average*sampleCount + i) / ++sampleCount;
|
|
}
|
|
|
|
|
|
@Override
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
/**
|
|
* @return current value of the counter
|
|
*/
|
|
@Override
|
|
public int getValue(){
|
|
return counter.intValue();
|
|
}
|
|
/**
|
|
* @return the maximum registered value over the lifetime of the counter
|
|
*/
|
|
@Override
|
|
public int getMax() {
|
|
return max;
|
|
}
|
|
/**
|
|
* @return the minimum registered value over the lifetime of the counter
|
|
*/
|
|
@Override
|
|
public int getMin() {
|
|
return min;
|
|
}
|
|
/**
|
|
* @return the average value of the counter
|
|
*/
|
|
@Override
|
|
public double getAverage() {
|
|
return average;
|
|
}
|
|
}
|
|
}
|