Metrics数据的输出格式

Metrics的Histogram可配置项

这篇是之前监控工具——Metrics 快速入门的补充

代码地址

因为每个例子涉及代码较多,且包含测试用例,如果都贴到文章中内容过多,所以只贴出了部分代码。全部的代码在这里: https://gitee.com/daifyutils/springboot-samples

此篇文章所属模块为:base-metrics

支持的格式

Metric提供了Reporter接口可以对统计的指标进行不同格式的输出。

其提供的基础的输出类型包含:控制台、CSV、Slf4j、JMX、MetricsServlet

控制台

ConsoleReporter 主要用在调试模式,其会将内容输出到控制台中

其配置方法

public static void main(String[] args) throws InterruptedException, IOException {
        // 创建一个度量
        MetricRegistry registry = new MetricRegistry();
        // 注册到控制台中
        ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build();
        // 每5秒输出一次结果
        reporter.start(5, TimeUnit.SECONDS);

        Timer timer = registry.timer(MetricRegistry.name(TimersTest.class,"get-latency"));

        Timer.Context ctx;

        while(true){
            ctx = timer.time();
            Thread.sleep(random.nextInt(1000));
            ctx.stop();
        }
    }

输出内容

这个时候内容会按照5秒钟的间隔打印出MetricRegistry所有指标的度量信息,不同的指标使用-----------------分割

22-5-9 23:39:16 ================================================================

-- Timers ----------------------------------------------------------------------
dai.samples.metrics.TimersTest.get-latency
             count = 13
         mean rate = 2.60 calls/second
     1-minute rate = 0.00 calls/second
     5-minute rate = 2.60 calls/second
    15-minute rate = 2.60 calls/second
               min = 13.94 milliseconds
               max = 885.82 milliseconds
              mean = 371.01 milliseconds
            stddev = 298.94 milliseconds
            median = 204.48 milliseconds
              75% <= 683.32 milliseconds
              95% <= 885.82 milliseconds
              98% <= 885.82 milliseconds
              99% <= 885.82 milliseconds
            99.9% <= 885.82 milliseconds


22-5-9 23:39:21 ================================================================

-- Timers ----------------------------------------------------------------------
dai.samples.metrics.TimersTest.get-latency
             count = 22
         mean rate = 2.20 calls/second
     1-minute rate = 2.60 calls/second
     5-minute rate = 2.60 calls/second
    15-minute rate = 2.60 calls/second
               min = 13.94 milliseconds
               max = 975.09 milliseconds
              mean = 456.54 milliseconds
            stddev = 325.83 milliseconds
            median = 513.01 milliseconds
              75% <= 715.50 milliseconds
              95% <= 972.52 milliseconds
              98% <= 975.09 milliseconds
              99% <= 975.09 milliseconds
            99.9% <= 975.09 milliseconds
CSV

其配置方法

public static void main(String[] args) throws InterruptedException {
        // 创建一个度量
        MetricRegistry registry = new MetricRegistry();
        // 注册到控制台中
        CsvReporter reporter = CsvReporter.forRegistry(registry)
                .formatFor(Locale.CHINA)
                .convertRatesTo(TimeUnit.SECONDS)
                .convertDurationsTo(TimeUnit.MILLISECONDS)
                // CSV地址
                .build(new File("E:\\reporters"));
        // 每5秒输出一次结果
        reporter.start(5, TimeUnit.SECONDS);

        Timer timer = registry.timer(MetricRegistry.name(TimersTest.class,"latency"));
        Timer.Context ctx;

        while(true){
            ctx = timer.time();
            Thread.sleep(random.nextInt(1000));
            ctx.stop();
        }
    }

输出内容

其内容输出到指定的目录下,文件名称为MetricRegistry.name(TimersTest.class,"latency")的值(本例子中为dai.samples.metrics.TimersTest.latency.csv)输出的格式为

监控通道信息导出 监控导出来用什么格式_spring boot

Slf4j

其配置方法

public static void main(String[] args) throws InterruptedException {
        // 创建一个度量
        MetricRegistry registry = new MetricRegistry();
        // 注册到控制台中
        Slf4jReporter reporter = Slf4jReporter.forRegistry(registry)
                .outputTo(LoggerFactory.getLogger("com.example.metrics"))
                .convertRatesTo(TimeUnit.SECONDS)
                .convertDurationsTo(TimeUnit.MILLISECONDS)
                .build();
        // 每5秒输出一次结果
        reporter.start(5, TimeUnit.SECONDS);

        Timer timer = registry.timer(MetricRegistry.name(TimersTest.class,"get-latency"));
        Timer.Context ctx;

        while(true){
            ctx = timer.time();
            Thread.sleep(random.nextInt(1000));
            ctx.stop();
        }
    }

输出内容

使用Slf4j后,打印内容将受到log配置格式的控制,并可以输入到log中

Connected to the target VM, address: '127.0.0.1:13161', transport: 'socket'
23:43:06.566 [metrics-logger-reporter-1-thread-1] INFO dai.samples.reporters.Slf4jReporters - type=TIMER, name=dai.samples.metrics.TimersTest.get-latency, count=7, min=35.1732, max=974.173, mean=637.6869527750133, stddev=296.0382587938576, median=615.7707, p75=972.7867, p95=974.173, p98=974.173, p99=974.173, p999=974.173, mean_rate=1.4002949301181815, m1=0.0, m5=0.0, m15=0.0, rate_unit=events/second, duration_unit=milliseconds
23:43:11.559 [metrics-logger-reporter-1-thread-1] INFO dai.samples.reporters.Slf4jReporters - type=TIMER, name=dai.samples.metrics.TimersTest.get-latency, count=16, min=35.1732, max=974.173, mean=580.3104276645525, stddev=267.0479627424082, median=634.7826, p75=710.237, p95=974.173, p98=974.173, p99=974.173, p999=974.173, mean_rate=1.6010734236661628, m1=1.4, m5=1.4, m15=1.4, rate_unit=events/second, duration_unit=milliseconds
JMX

JMX格式并不建议在生产环境中使用,对于开发环境或者某些需要追踪系统问题的场景下可以使用此方式。

其配置方法

public static void main(String[] args) throws InterruptedException {
        // 创建一个度量
        MetricRegistry registry = new MetricRegistry();
        // 注册到控制台中
        JmxReporter reporter = JmxReporter.forRegistry(registry).build();
        reporter.start();

        Timer timer = registry.timer(MetricRegistry.name(TimersTest.class,"latency"));

        Timer.Context ctx;

        while(true){
            ctx = timer.time();
            Thread.sleep(random.nextInt(1000));
            ctx.stop();
        }
    }

查看输出内容

JmxReporter需要使用JConsole 查看可以从命令行直接输入jconsole或在 GUI shell中运行。

在Mbean中可以看到metrics监控的指标,以及各个度量的值

监控通道信息导出 监控导出来用什么格式_java_02

监控通道信息导出 监控导出来用什么格式_开发语言_03

输出度量过滤

实际使用中MetricRegistry会设置多种度量,在不同的场景下我们需要打印我们需要的度量,而Metric提供了MetricFilter接口来过滤需要打印的内容

其配置方法

private static Queue<String> queue = new LinkedList<String>();

    private static Counter counter;

    private static Random random = new Random();


    public static void main(String[] args) throws InterruptedException, IOException {
        // 创建一个度量
        MetricRegistry registry = new MetricRegistry();
        // 注册到控制台中
        ConsoleReporter reporter = ConsoleReporter.forRegistry(registry)
                .filter((name, metric) -> Objects.equals(MetricRegistry.name(GaugesTest.class, "queue", "size"),name))
                .build();
        // 每5秒输出一次结果
        reporter.start(5, TimeUnit.SECONDS);
        Gauge gauge = () -> queue.size();
        // 注册统计内容
        registry.register(MetricRegistry.name(GaugesTest.class, "queue", "size"),gauge);
        counter = registry.counter(MetricRegistry.name(Queue.class,"jobs","size"));


        int num = 1;
        while(true){
            Thread.sleep(200);
            if (random.nextDouble() > 0.7){
                String job = takeJob();
            }else{
                String job = "Job-"+num;
                addJob(job);
            }
            num++;
        }
    }

    private static void addJob(String job) {
        counter.inc();
        queue.offer(job);
    }

    private static String takeJob() {
        counter.dec();
        return queue.poll();
    }

输出内容

在添加了filter((name, metric) -> Objects.equals(MetricRegistry.name(GaugesTest.class, "queue", "size"),name)过滤后,控制台中只会打印我们需要的内容

22-5-9 23:25:04 ================================================================

-- Gauges ----------------------------------------------------------------------
dai.samples.metrics.GaugesTest.queue.size
             value = 3265


22-5-9 23:25:09 ================================================================

-- Gauges ----------------------------------------------------------------------
dai.samples.metrics.GaugesTest.queue.size
             value = 3265