一个简单分析监测类的实现

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件事");

        //打印第5件事处理的时间
        Monitor.now();
        doSomeThing("第5件事,小事");
        Monitor.done("处理第5件事", "小事");

        doSomeThing("第6件事");

        //打印第7件事处理的时间
        Monitor.now();
        for (int i = 0; i < 5; i++) {
            Monitor.counter("第7件事处理次数");
            doSomeThing("第7件事");
        }
        Monitor.done("多次处理第7件事");

        doSomeThing("第8件事");

        //处理第9件事,收集但是不打印统计信息
        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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值