java-工具包-Metrics
java-工具包-Mertrics
一. 概述
对业务代码的各个指标进行监控
Metrics能够很好的跟Ganlia、Graphite结合
<dependency>
  <groupId>com.codahale.metrics</groupId>
  <artifactId>metrics-core</artifactId>
  <version>3.0.1</version>
</dependency>
core包主要提供如下核心功能:
- Metrics Registries类似一个metrics容器,维护一个Map,可以是一个服务一个实例。
- 支持五种metric类型:Gauges、Counters、Meters、Histograms和Timers。
- 可以将metrics值通过JMX、Console,CSV文件和SLF4J loggers发布出来。
二. 五种Metrics类型
Gauges
统计瞬时状态的数据信息,比如系统中处于pending状态的job
使用例子
public class MetricsTest {
    private static final MetricRegistry metrics = new MetricRegistry();
    private static Queue<String> queue = new LinkedBlockingDeque<String>();
    private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
    @Test
    public void TestGauges() throws InterruptedException {
        reporter.start(3, TimeUnit.SECONDS);
        //实例化一个Gauge
        Gauge<Integer> gauge = new Gauge<Integer>() {
            @Override
            public Integer getValue() {
                return queue.size();
            }
        };
        //注册到容器中
        metrics.register(MetricRegistry.name(MetricsTest.class, "pending-job", "size"), gauge);
        //模拟数据
        for (int i=0; i<20; i++){
            queue.add("a");
            Thread.sleep(1000);
        }
    }
}
同时,提供的几种默认Gauge如下
- JMX Gauges—提供给第三方库只通过JMX将指标暴露出来。
- Ratio Gauges—简单地通过创建一个gauge计算两个数的比值。
- Cached Gauges—对某些计量指标提供缓存
Counter
public class TestCounter {
    private static final MetricRegistry metrics = new MetricRegistry();
    private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
    private static Counter pendingJobs = metrics.counter(name(TestCounter.class, "pedding-jobs"));
    private static Queue<String> queue = new LinkedList<String>();
    public static void add(String str) {
        pendingJobs.inc();
        queue.offer(str);
    }
    public String take() {
        pendingJobs.dec();
        return queue.poll();
    }
    public static void main(String[]args) throws InterruptedException {
        reporter.start(3, TimeUnit.SECONDS);
        while(true){
            add("1");
            Thread.sleep(1000);
        }
    }
}
Meters
用来度量某个时间段的平均处理次数,每1、5、15分钟的TPS。比如一个service的请求数,通过metrics.meter()实例化一个Meter之后,然后通过meter.mark()方法就能将本次请求记录下来。统计结果有总的请求数,平均每秒的请求数,以及最近的1、5、15分钟的平均TPS。
public class TestMeters {
    private static final MetricRegistry metrics = new MetricRegistry();
    private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
    private static final Meter requests = metrics.meter(name(TestMeters.class, "request"));
    public static void handleRequest() {
        requests.mark();
    }
    public static void main(String[] args) throws InterruptedException {
        reporter.start(3, TimeUnit.SECONDS);
        while(true){
            handleRequest();
            Thread.sleep(100);
        }
    }
}
Histograms
Histograms主要使用来统计数据的分布情况,最大值、最小值、平均值、中位数,百分比(75%、90%、95%、98%、99%和99.9%)。例如,需要统计某个页面的请求响应时间分布情况,可以使用该种类型的Metrics进行统计。具体的样例代码如下
public class TestHistograms {
    private static final MetricRegistry metrics = new MetricRegistry();
    private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
    private static final Histogram randomNums = metrics.histogram(name(TestHistograms.class, "random"));
    public static void handleRequest(double random) {
        randomNums.update((int) (random*100));
    }
    public static void main(String[] args) throws InterruptedException {
        reporter.start(3, TimeUnit.SECONDS);
        Random rand = new Random();
        while(true){
            handleRequest(rand.nextDouble());
            Thread.sleep(100);
        }
    }
}
Timers
Timers主要是用来统计某一块代码段的执行时间以及其分布情况,具体是基于Histograms和Meters来实现的。样例代码如下:
public class TestTimers {
    private static final MetricRegistry metrics = new MetricRegistry();
    private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
    private static final Timer requests = metrics.timer(name(TestTimers.class, "request"));
    public static void handleRequest(int sleep) {
        Timer.Context context = requests.time();
        try {
            //some operator
            Thread.sleep(sleep);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            context.stop();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        reporter.start(3, TimeUnit.SECONDS);
        Random random = new Random();
        while(true){
            handleRequest(random.nextInt(1000));
        }
    }
}
Health Checks
一个独立的模块
<dependency>                                    
  <groupId>com.codahale.metrics</groupId>       
  <artifactId>metrics-healthchecks</artifactId> 
  <version>3.0.1</version>         
</dependency>
使用起来和与上述几种类型的Metrics有点类似,但是需要重新实例化一个Metrics容器HealthCheckRegistry,待检测模块继承抽象类HealthCheck并实现check()方法即可,然后将该模块注册到HealthCheckRegistry中,判断的时候通过isHealthy()接口即可。
public class DatabaseHealthCheck extends HealthCheck{
    private final Database database;
    public DatabaseHealthCheck(Database database) {
        this.database = database;
    }
    @Override
    protected Result check() throws Exception {
        if (database.ping()) {
            return Result.healthy();
        }
        return Result.unhealthy("Can't ping database.");
    }
    static class Database {
        public boolean ping() {
            Random random = new Random();
            return random.nextBoolean();
        }
    }
    public static void main(String[] args) {
        HealthCheckRegistry registry = new HealthCheckRegistry();
        registry.register("database1", new DatabaseHealthCheck(new Database()));
        registry.register("database2", new DatabaseHealthCheck(new Database()));
        while (true) {
            for (Map.Entry<String, Result> entry : registry.runHealthChecks().entrySet()) {
                if (entry.getValue().isHealthy()) {
                    System.out.println(entry.getKey() + ": OK");
                } else {
                    System.err.println(entry.getKey() + ": FAIL, error message: " + entry.getValue().getMessage());
                    final Throwable e = entry.getValue().getError();
                    if (e != null) {
                        e.printStackTrace();
                    }
                }
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
        }
    }
}
其他支持
metrics提供了对Ehcache、Apache HttpClient、JDBI、Jersey、Jetty、Log4J、Logback、JVM等的集成,可以方便地将Metrics输出到Ganglia、Graphite中,供用户图形化展示。
 
                    
                
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号