1. 一个简单分析监测类的实现
package com.frlh.common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
/**
* 简易分析监测类
* <p>
* 1. {@link #finish()}只能统计距离最近的从{@link #start(String)}开始的所用时间,且不支持嵌套;
* 2. 本类中大多数函数的日志级别为info,{@link #done(String, String...)}中的统计信息只会在debug级别打印;
* 3. 可以在任意位置调用{@link #disable()}关闭监测函数。
* 4. 开始函数:
* {@link #start(String)} 开始监测,并设立第一个普通监测点
* 5. 标记函数:
* {@link #now()} 标记普通监测点
* {@link #mark(String)} 标记特定工作监测点
* 6. 收集函数:
* {@link #done(String, String...)} 优先匹配特定工作监测点;如果没有找到,则匹配普通监测点。打印监测点到本函数消耗的时间,并将这段时间归入某统计组。
* 7. 结束函数
* {@link #finish()} 结束监测,打印统计信息
* <p>
* Created by LH on 2017/12/21.
*/
public class Monitor {
private static Logger log = LoggerFactory.getLogger("Monitor");
private static boolean enabled = true;
private static String monitorWork;
private static ThreadLocal<Long> startTime = new ThreadLocal<>();
private static ThreadLocal<Long> lastTime = new ThreadLocal<>();
private static ThreadLocal<Map<String, Long>> doing = new ThreadLocal<>();
private static ThreadLocal<Map<String, Long>> group = new ThreadLocal<>();
private static ThreadLocal<Map<String, Long>> count = new ThreadLocal<>();
/**
* 关闭所有监测函数
*/
public static void disable() {
enabled = false;
}
/**
* 设立一个计数器
*
* @param counterName 计数器名称
*/
public static void counter(String counterName) {
if (enabled) {
count.get().put(counterName, count.get().getOrDefault(counterName, 0L) + 1);
}
}
/**
* 开始监测
*
* @param work 受监测的工作名称
*/
public static void start(String work) {
if (enabled) {
monitorWork = work;
long tmp = System.currentTimeMillis();
startTime.set(tmp);
lastTime.set(tmp);
doing.set(new HashMap<>());
group.set(new HashMap<>());
count.set(new HashMap<>());
log.info(Thread.currentThread().getName() + "--> start time: " + tmp + " to do " + work);
}
}
/**
* 标记普通监测点(刷新时间点)
*/
public static void now() {
if (enabled) {
long tmp = System.currentTimeMillis();
lastTime.set(tmp);
}
}
/**
* 标记特定工作监测点(设立某项工作的开始点)
*
* @param work 受监测的工作名称
*/
public static void mark(String work) {
if (enabled) {
long tmp = System.currentTimeMillis();
doing.get().put(work, tmp);
}
}
/**
* 打印本工作的消耗时间,优先按照参数work匹配{@link #mark(String work)},然后匹配start()、now()、done();
* 并且把本工作的消耗时间归入某统计组
*
* @param work 受监测的工作名称
* @param groups 本工作的消耗时间归入哪些统计组
*/
public static void done(String work, String... groups) {
if (enabled) {
long tmp = System.currentTimeMillis();
long time = tmp - doing.get().getOrDefault(work, lastTime.get());
if (groups != null) {
for (int i = 0; i < groups.length; i++) {
group.get().put(groups[i], time + group.get().getOrDefault(groups[i], 0L));
}
}
log.debug(Thread.currentThread().getName() + "--> spend time: " + time + " to do " + work);
lastTime.set(tmp);
}
}
/**
* 结束统计,并且打印相关统计结果
* <p>
* 统计的结果包括3个部分:各个计数器的计数次数,各个统计组的统计时间,整个工作的总时间
*/
public static void finish() {
if (enabled) {
long tmp = System.currentTimeMillis();
log.info(Thread.currentThread().getName() + "--> finish time: " + tmp + " to do " + monitorWork);
log.info("--------------------------------------------------------------------------------");
log.info("Count Number: ");
Map<String, Long> countNumbers = count.get();
for (Map.Entry countNumber : countNumbers.entrySet()) {
log.info(Thread.currentThread().getName() + "--> " + countNumber.getKey() + " is: " + countNumber.getValue());
}
log.info("Group Time: ");
Map<String, Long> groupTimes = group.get();
for (Map.Entry groupTime : groupTimes.entrySet()) {
log.info(Thread.currentThread().getName() + "--> " + groupTime.getKey() + " spend time: " + groupTime.getValue());
}
log.info(Thread.currentThread().getName() + "--> All spend time: " + (tmp - startTime.get()) + "\n\n");
}
}
}
2. 使用示例
package com.frlh.common;
import java.util.Random;
/**
* 简易分析监测类--使用示例
* <p>
* Created by frlh on 2017/12/21.
*/
public class MonitorT {
public static void doSomeThing(String someThing) {
Random random = new Random();
try {
System.out.println("正在进行:" + someThing);
int time = random.nextInt() % 300;
time *= time;
Thread.sleep(time % 3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Monitor.start("统计示例");
doSomeThing("第1件事");
doSomeThing("第2件事");
Monitor.done("初始化,第1,2件事");
Monitor.mark("主要工作");
doSomeThing("第3件事,大事");
Monitor.done("处理第3件事", "大事");
doSomeThing("第4件事");
Monitor.now();
doSomeThing("第5件事,小事");
Monitor.done("处理第5件事", "小事");
doSomeThing("第6件事");
Monitor.now();
for (int i = 0; i < 5; i++) {
Monitor.counter("第7件事处理次数");
doSomeThing("第7件事");
}
Monitor.done("多次处理第7件事");
doSomeThing("第8件事");
Monitor.now();
doSomeThing("第9件事,大事");
Monitor.done("第9件事", "大事");
doSomeThing("第10件事");
Monitor.done("主要工作", "主要工作");
Monitor.finish();
}
}
3. 示例程序运行结果
2017-12-22 21:48:15,784 INFO Monitor [73] [main] - main--> start time: 1513950495783 to do 统计示例
正在进行:第1件事
正在进行:第2件事
2017-12-22 21:48:18,041 DEBUG Monitor [115] [main] - main--> spend time: 2258 to do 初始化,第1,2件事
正在进行:第3件事,大事
2017-12-22 21:48:18,812 DEBUG Monitor [115] [main] - main--> spend time: 771 to do 处理第3件事
正在进行:第4件事
正在进行:第5件事,小事
2017-12-22 21:48:23,744 DEBUG Monitor [115] [main] - main--> spend time: 2401 to do 处理第5件事
正在进行:第6件事
正在进行:第7件事
正在进行:第7件事
正在进行:第7件事
正在进行:第7件事
正在进行:第7件事
2017-12-22 21:48:29,714 DEBUG Monitor [115] [main] - main--> spend time: 5008 to do 多次处理第7件事
正在进行:第8件事
正在进行:第9件事,大事
2017-12-22 21:48:33,333 DEBUG Monitor [115] [main] - main--> spend time: 2289 to do 第9件事
正在进行:第10件事
2017-12-22 21:48:35,235 DEBUG Monitor [115] [main] - main--> spend time: 17193 to do 主要工作
2017-12-22 21:48:35,235 INFO Monitor [128] [main] - main--> finish time: 1513950515235 to do 统计示例
2017-12-22 21:48:35,236 INFO Monitor [129] [main] - --------------------------------------------------------------------------------
2017-12-22 21:48:35,238 INFO Monitor [130] [main] - Count Number:
2017-12-22 21:48:35,239 INFO Monitor [133] [main] - main--> 第7件事处理次数 is: 5
2017-12-22 21:48:35,240 INFO Monitor [135] [main] - Group Time:
2017-12-22 21:48:35,240 INFO Monitor [138] [main] - main--> 主要工作 spend time: 17193
2017-12-22 21:48:35,241 INFO Monitor [138] [main] - main--> 小事 spend time: 2401
2017-12-22 21:48:35,241 INFO Monitor [138] [main] - main--> 大事 spend time: 3060
2017-12-22 21:48:35,242 INFO Monitor [140] [main] - main--> All spend time: 19452