<< 如何使用百度云下载电影等热门资源 - 忘我的追寻 | 首页 | Metrics 1.3.6 >>

java版的Metric工具介绍-hustfxj-ChinaUnix博客

Metrics是一个给JAVA服务的各项指标提供度量工具的包,在JAVA代码中嵌入Metrics代码,可以方便的对业务代码的各个指标进行监控,同时,Metrics能够很好的跟Ganlia、Graphite结合,方便的提供图形化接口。基本使用方式直接将core包(目前稳定版本3.0.1)导入pom文件即可,配置如下:

<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类型:

1.       Gauges

Gauges是一个最简单的计量,一般用来统计瞬时状态的数据信息,比如系统中处于pending状态的job。测试代码
 

点击(此处)折叠或打开

  1. package com.netease.test.metrics;
  2.  
  3. import com.codahale.metrics.ConsoleReporter;
  4. import com.codahale.metrics.Gauge;
  5. import com.codahale.metrics.JmxReporter;
  6. import com.codahale.metrics.MetricRegistry;
  7.  
  8. import java.util.Queue;
  9. import java.util.concurrent.LinkedBlockingDeque;
  10. import java.util.concurrent.TimeUnit;
  11.  
  12. /**
  13.  * User: hzwangxx
  14.  * Date: 14-2-17
  15.  * Time: 14:47
  16.  * 测试Gauges,实时统计pending状态的job个数
  17.  */
  18. public class TestGauges {
  19.     /**
  20.      * 实例化一个registry,最核心的一个模块,相当于一个应用程序的metrics系统的容器,维护一个Map
  21.      */
  22.     private static final MetricRegistry metrics = new MetricRegistry();
  23.  
  24.     private static Queue<String> queue = new LinkedBlockingDeque<String>();
  25.  
  26.     /**
  27.      * 在控制台上打印输出
  28.      */
  29.     private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
  30.  
  31.     public static void main(String[] args) throws InterruptedException {
  32.         reporter.start(3, TimeUnit.SECONDS);
  33.  
  34.         //实例化一个Gauge
  35.         Gauge<Integer> gauge = new Gauge<Integer>() {
  36.             @Override
  37.             public Integer getValue() {
  38.                 return queue.size();
  39.             }
  40.         };
  41.  
  42.         //注册到容器中
  43.         metrics.register(MetricRegistry.name(TestGauges.class, "pending-job", "size"), gauge);
  44.  
  45.         //测试JMX
  46.         JmxReporter jmxReporter = JmxReporter.forRegistry(metrics).build();
  47.         jmxReporter.start();
  48.  
  49.         //模拟数据
  50.         for (int i=0; i<20; i++){
  51.             queue.add("a");
  52.             Thread.sleep(1000);
  53.         }
  54.  
  55.     }
  56. }
  57.  
  58. /*
  59. console output:
  60. 14-2-17 15:29:35 ===============================================================
  61.  
  62. -- Gauges ----------------------------------------------------------------------
  63. com.netease.test.metrics.TestGauges.pending-job.size
  64.              value = 4
  65.  
  66.  
  67. 14-2-17 15:29:38 ===============================================================
  68.  
  69. -- Gauges ----------------------------------------------------------------------
  70. com.netease.test.metrics.TestGauges.pending-job.size
  71.              value = 6
  72.  
  73.  
  74. 14-2-17 15:29:41 ===============================================================
  75.  
  76. -- Gauges ----------------------------------------------------------------------
  77. com.netease.test.metrics.TestGauges.pending-job.size
  78.              value = 9
  79.  */

 

通过以上步骤将会向MetricsRegistry容器中注册一个名字为com.netease.test.metrics .TestGauges.pending-job.size的metrics,实时获取队列长度的指标。另外,Core包种还扩展了几种特定的Gauge:
  • JMX Gauges—提供给第三方库只通过JMX将指标暴露出来。
  • Ratio Gauges—简单地通过创建一个gauge计算两个数的比值。
  • Cached Gauges—对某些计量指标提供缓存

Derivative Gauges—提供Gauge的值是基于其他Gauge值的接口。

2.       Counter

Counter是Gauge的一个特例,维护一个计数器,可以通过inc()和dec()方法对计数器做修改。使用步骤与Gauge基本类似,在MetricRegistry中提供了静态方法可以直接实例化一个Counter。

 

点击(此处)折叠或打开

  1. package com.netease.test.metrics;
  2.  
  3. import com.codahale.metrics.ConsoleReporter;
  4. import com.codahale.metrics.Counter;
  5. import com.codahale.metrics.MetricRegistry;
  6.  
  7. import java.util.LinkedList;
  8. import java.util.Queue;
  9. import java.util.concurrent.TimeUnit;
  10. import static com.codahale.metrics.MetricRegistry.*;
  11. /**
  12.  * User: hzwangxx
  13.  * Date: 14-2-14
  14.  * Time: 14:02
  15.  * 测试Counter
  16.  */
  17. public class TestCounter {
  18.  
  19.     /**
  20.      * 实例化一个registry,最核心的一个模块,相当于一个应用程序的metrics系统的容器,维护一个Map
  21.      */
  22.     private static final MetricRegistry metrics = new MetricRegistry();
  23.  
  24.     /**
  25.      * 在控制台上打印输出
  26.      */
  27.     private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
  28.  
  29.     /**
  30.      * 实例化一个counter,同样可以通过如下方式进行实例化再注册进去
  31.      * pendingJobs = new Counter();
  32.      * metrics.register(MetricRegistry.name(TestCounter.class, "pending-jobs"), pendingJobs);
  33.      */
  34.     private static Counter pendingJobs = metrics.counter(name(TestCounter.class, "pedding-jobs"));
  35. // private static Counter pendingJobs = metrics.counter(MetricRegistry.name(TestCounter.class, "pedding-jobs"));
  36.  
  37.  
  38.  
  39.     private static Queue<String> queue = new LinkedList<String>();
  40.  
  41.     public static void add(String str) {
  42.         pendingJobs.inc();
  43.         queue.offer(str);
  44.     }
  45.  
  46.     public String take() {
  47.         pendingJobs.dec();
  48.         return queue.poll();
  49.     }
  50.  
  51.     public static void main(String[]args) throws InterruptedException {
  52.         reporter.start(3, TimeUnit.SECONDS);
  53.         while(true){
  54.             add("1");
  55.             Thread.sleep(1000);
  56.         }
  57.  
  58.     }
  59. }
  60.  
  61. /*
  62. console output:
  63. 14-2-17 17:52:34 ===============================================================
  64.  
  65. -- Counters --------------------------------------------------------------------
  66. com.netease.test.metrics.TestCounter.pedding-jobs
  67.              count = 4
  68.  
  69.  
  70. 14-2-17 17:52:37 ===============================================================
  71.  
  72. -- Counters --------------------------------------------------------------------
  73. com.netease.test.metrics.TestCounter.pedding-jobs
  74.              count = 6
  75.  
  76.  
  77. 14-2-17 17:52:40 ===============================================================
  78.  
  79. -- Counters --------------------------------------------------------------------
  80. com.netease.test.metrics.TestCounter.pedding-jobs
  81.              count = 9
  82.  
  83.  */

 

3.       Meters

Meters用来度量某个时间段的平均处理次数(request per second),每1、5、15分钟的TPS。比如一个service的请求数,通过metrics.meter()实例化一个Meter之后,然后通过meter.mark()方法就能将本次请求记录下来。统计结果有总的请求数,平均每秒的请求数,以及最近的1、5、15分钟的平均TPS。

 

点击(此处)折叠或打开

  1. package com.netease.test.metrics;
  2.  
  3. import com.codahale.metrics.ConsoleReporter;
  4. import com.codahale.metrics.Meter;
  5. import com.codahale.metrics.MetricRegistry;
  6.  
  7. import java.util.concurrent.TimeUnit;
  8.  
  9. import static com.codahale.metrics.MetricRegistry.*;
  10.  
  11. /**
  12.  * User: hzwangxx
  13.  * Date: 14-2-17
  14.  * Time: 18:34
  15.  * 测试Meters
  16.  */
  17. public class TestMeters {
  18.     /**
  19.      * 实例化一个registry,最核心的一个模块,相当于一个应用程序的metrics系统的容器,维护一个Map
  20.      */
  21.     private static final MetricRegistry metrics = new MetricRegistry();
  22.  
  23.     /**
  24.      * 在控制台上打印输出
  25.      */
  26.     private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
  27.  
  28.     /**
  29.      * 实例化一个Meter
  30.      */
  31.     private static final Meter requests = metrics.meter(name(TestMeters.class, "request"));
  32.  
  33.     public static void handleRequest() {
  34.         requests.mark();
  35.     }
  36.  
  37.     public static void main(String[] args) throws InterruptedException {
  38.         reporter.start(3, TimeUnit.SECONDS);
  39.         while(true){
  40.             handleRequest();
  41.             Thread.sleep(100);
  42.         }
  43.     }
  44.  
  45. }
  46.  
  47. /*
  48. 14-2-17 18:43:08 ===============================================================
  49.  
  50. -- Meters ----------------------------------------------------------------------
  51. com.netease.test.metrics.TestMeters.request
  52.              count = 30
  53.          mean rate = 9.95 events/second
  54.      1-minute rate = 0.00 events/second
  55.      5-minute rate = 0.00 events/second
  56.     15-minute rate = 0.00 events/second
  57.  
  58.  
  59. 14-2-17 18:43:11 ===============================================================
  60.  
  61. -- Meters ----------------------------------------------------------------------
  62. com.netease.test.metrics.TestMeters.request
  63.              count = 60
  64.          mean rate = 9.99 events/second
  65.      1-minute rate = 10.00 events/second
  66.      5-minute rate = 10.00 events/second
  67.     15-minute rate = 10.00 events/second
  68.  
  69.  
  70. 14-2-17 18:43:14 ===============================================================
  71.  
  72. -- Meters ----------------------------------------------------------------------
  73. com.netease.test.metrics.TestMeters.request
  74.              count = 90
  75.          mean rate = 9.99 events/second
  76.      1-minute rate = 10.00 events/second
  77.      5-minute rate = 10.00 events/second
  78.     15-minute rate = 10.00 events/second
  79. */

 

4.       Histograms

Histograms主要使用来统计数据的分布情况,最大值、最小值、平均值、中位数,百分比(75%、90%、95%、98%、99%和99.9%)。例如,需要统计某个页面的请求响应时间分布情况,可以使用该种类型的Metrics进行统计。具体的样例代码如下:

 

点击(此处)折叠或打开

  1. package com.netease.test.metrics;
  2.  
  3. import com.codahale.metrics.ConsoleReporter;
  4. import com.codahale.metrics.Histogram;
  5. import com.codahale.metrics.MetricRegistry;
  6.  
  7. import java.util.Random;
  8. import java.util.concurrent.TimeUnit;
  9.  
  10. import static com.codahale.metrics.MetricRegistry.name;
  11.  
  12. /**
  13.  * User: hzwangxx
  14.  * Date: 14-2-17
  15.  * Time: 18:34
  16.  * 测试Histograms
  17.  */
  18. public class TestHistograms {
  19.     /**
  20.      * 实例化一个registry,最核心的一个模块,相当于一个应用程序的metrics系统的容器,维护一个Map
  21.      */
  22.     private static final MetricRegistry metrics = new MetricRegistry();
  23.  
  24.     /**
  25.      * 在控制台上打印输出
  26.      */
  27.     private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
  28.  
  29.     /**
  30.      * 实例化一个Histograms
  31.      */
  32.     private static final Histogram randomNums = metrics.histogram(name(TestHistograms.class, "random"));
  33.  
  34.     public static void handleRequest(double random) {
  35.         randomNums.update((int) (random*100));
  36.     }
  37.  
  38.     public static void main(String[] args) throws InterruptedException {
  39.         reporter.start(3, TimeUnit.SECONDS);
  40.         Random rand = new Random();
  41.         while(true){
  42.             handleRequest(rand.nextDouble());
  43.             Thread.sleep(100);
  44.         }
  45.     }
  46.  
  47. }
  48.  
  49. /*
  50. 14-2-17 19:39:11 ===============================================================
  51.  
  52. -- Histograms ------------------------------------------------------------------
  53. com.netease.test.metrics.TestHistograms.random
  54.              count = 30
  55.                min = 1
  56.                max = 97
  57.               mean = 45.93
  58.             stddev = 29.12
  59.             median = 39.50
  60.               75% <= 71.00
  61.               95% <= 95.90
  62.               98% <= 97.00
  63.               99% <= 97.00
  64.             99.9% <= 97.00
  65.  
  66.  
  67. 14-2-17 19:39:14 ===============================================================
  68.  
  69. -- Histograms ------------------------------------------------------------------
  70. com.netease.test.metrics.TestHistograms.random
  71.              count = 60
  72.                min = 0
  73.                max = 97
  74.               mean = 41.17
  75.             stddev = 28.60
  76.             median = 34.50
  77.               75% <= 69.75
  78.               95% <= 92.90
  79.               98% <= 96.56
  80.               99% <= 97.00
  81.             99.9% <= 97.00
  82.  
  83.  
  84. 14-2-17 19:39:17 ===============================================================
  85.  
  86. -- Histograms ------------------------------------------------------------------
  87. com.netease.test.metrics.TestHistograms.random
  88.              count = 90
  89.                min = 0
  90.                max = 97
  91.               mean = 44.67
  92.             stddev = 28.47
  93.             median = 43.00
  94.               75% <= 71.00
  95.               95% <= 91.90
  96.               98% <= 96.18
  97.               99% <= 97.00
  98.             99.9% <= 97.00
  99. */



5.       Timers

 

Timers主要是用来统计某一块代码段的执行时间以及其分布情况,具体是基于Histograms和Meters来实现的。样例代码如下:
 

点击(此处)折叠或打开

  1. package com.netease.test.metrics;
  2.  
  3. import com.codahale.metrics.ConsoleReporter;
  4. import com.codahale.metrics.MetricRegistry;
  5. import com.codahale.metrics.Timer;
  6.  
  7. import java.util.Random;
  8. import java.util.concurrent.TimeUnit;
  9.  
  10. import static com.codahale.metrics.MetricRegistry.name;
  11.  
  12. /**
  13.  * User: hzwangxx
  14.  * Date: 14-2-17
  15.  * Time: 18:34
  16.  * 测试Timers
  17.  */
  18. public class TestTimers {
  19.     /**
  20.      * 实例化一个registry,最核心的一个模块,相当于一个应用程序的metrics系统的容器,维护一个Map
  21.      */
  22.     private static final MetricRegistry metrics = new MetricRegistry();
  23.  
  24.     /**
  25.      * 在控制台上打印输出
  26.      */
  27.     private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
  28.  
  29.     /**
  30.      * 实例化一个Meter
  31.      */
  32. // private static final Timer requests = metrics.timer(name(TestTimers.class, "request"));
  33.     private static final Timer requests = metrics.timer(name(TestTimers.class, "request"));
  34.  
  35.     public static void handleRequest(int sleep) {
  36.         Timer.Context context = requests.time();
  37.         try {
  38.             //some operator
  39.             Thread.sleep(sleep);
  40.         } catch (InterruptedException e) {
  41.             e.printStackTrace();
  42.         } finally {
  43.             context.stop();
  44.         }
  45.  
  46.     }
  47.  
  48.     public static void main(String[] args) throws InterruptedException {
  49.         reporter.start(3, TimeUnit.SECONDS);
  50.         Random random = new Random();
  51.         while(true){
  52.             handleRequest(random.nextInt(1000));
  53.         }
  54.     }
  55.  
  56. }
  57.  
  58. /*
  59. 14-2-18 9:31:54 ================================================================
  60.  
  61. -- Timers ----------------------------------------------------------------------
  62. com.netease.test.metrics.TestTimers.request
  63.              count = 4
  64.          mean rate = 1.33 calls/second
  65.      1-minute rate = 0.00 calls/second
  66.      5-minute rate = 0.00 calls/second
  67.     15-minute rate = 0.00 calls/second
  68.                min = 483.07 milliseconds
  69.                max = 901.92 milliseconds
  70.               mean = 612.64 milliseconds
  71.             stddev = 196.32 milliseconds
  72.             median = 532.79 milliseconds
  73.               75% <= 818.31 milliseconds
  74.               95% <= 901.92 milliseconds
  75.               98% <= 901.92 milliseconds
  76.               99% <= 901.92 milliseconds
  77.             99.9% <= 901.92 milliseconds
  78.  
  79.  
  80. 14-2-18 9:31:57 ================================================================
  81.  
  82. -- Timers ----------------------------------------------------------------------
  83. com.netease.test.metrics.TestTimers.request
  84.              count = 8
  85.          mean rate = 1.33 calls/second
  86.      1-minute rate = 1.40 calls/second
  87.      5-minute rate = 1.40 calls/second
  88.     15-minute rate = 1.40 calls/second
  89.                min = 41.07 milliseconds
  90.                max = 968.19 milliseconds
  91.               mean = 639.50 milliseconds
  92.             stddev = 306.12 milliseconds
  93.             median = 692.77 milliseconds
  94.               75% <= 885.96 milliseconds
  95.               95% <= 968.19 milliseconds
  96.               98% <= 968.19 milliseconds
  97.               99% <= 968.19 milliseconds
  98.             99.9% <= 968.19 milliseconds
  99.  
  100.  
  101. 14-2-18 9:32:00 ================================================================
  102.  
  103. -- Timers ----------------------------------------------------------------------
  104. com.netease.test.metrics.TestTimers.request
  105.              count = 15
  106.          mean rate = 1.67 calls/second
  107.      1-minute rate = 1.40 calls/second
  108.      5-minute rate = 1.40 calls/second
  109.     15-minute rate = 1.40 calls/second
  110.                min = 41.07 milliseconds
  111.                max = 968.19 milliseconds
  112.               mean = 591.35 milliseconds
  113.             stddev = 302.96 milliseconds
  114.             median = 650.56 milliseconds
  115.               75% <= 838.07 milliseconds
  116.               95% <= 968.19 milliseconds
  117.               98% <= 968.19 milliseconds
  118.               99% <= 968.19 milliseconds
  119.             99.9% <= 968.19 milliseconds
  120.  
  121. */

 

6  Health Checks

Metrics提供了一个独立的模块:Health Checks,用于对Application、其子模块或者关联模块的运行是否正常做检测。该模块是独立metrics-core模块的,使用时则导入metrics-healthchecks包。

<dependency> <groupId>com.codahale.metrics</groupId> <artifactId>metrics-healthchecks</artifactId> <version>3.0.1</version> </dependency>

使用起来和与上述几种类型的Metrics有点类似,但是需要重新实例化一个Metrics容器HealthCheckRegistry,待检测模块继承抽象类HealthCheck并实现check()方法即可,然后将该模块注册到HealthCheckRegistry中,判断的时候通过isHealthy()接口即可。如下示例代码:

 

点击(此处)折叠或打开

  1. package com.netease.test.metrics;
  2.  
  3. import com.codahale.metrics.health.HealthCheck;
  4. import com.codahale.metrics.health.HealthCheckRegistry;
  5.  
  6. import java.util.Map;
  7. import java.util.Random;
  8.  
  9. /**
  10.  * User: hzwangxx
  11.  * Date: 14-2-18
  12.  * Time: 9:57
  13.  */
  14. public class DatabaseHealthCheck extends HealthCheck{
  15.     private final Database database;
  16.  
  17.     public DatabaseHealthCheck(Database database) {
  18.         this.database = database;
  19.     }
  20.  
  21.     @Override
  22.     protected Result check() throws Exception {
  23.         if (database.ping()) {
  24.             return Result.healthy();
  25.         }
  26.         return Result.unhealthy("Can't ping database.");
  27.     }
  28.  
  29.     /**
  30.      * 模拟Database对象
  31.      */
  32.     static class Database {
  33.         /**
  34.          * 模拟database的ping方法
  35.          * @return 随机返回boolean值
  36.          */
  37.         public boolean ping() {
  38.             Random random = new Random();
  39.             return random.nextBoolean();
  40.         }
  41.     }
  42.  
  43.     public static void main(String[] args) {
  44. // MetricRegistry metrics = new MetricRegistry();
  45. // ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
  46.         HealthCheckRegistry registry = new HealthCheckRegistry();
  47.         registry.register("database1", new DatabaseHealthCheck(new Database()));
  48.         registry.register("database2", new DatabaseHealthCheck(new Database()));
  49.         while (true) {
  50.             for (Map.Entry<String, Result> entry : registry.runHealthChecks().entrySet()) {
  51.                 if (entry.getValue().isHealthy()) {
  52.                     System.out.println(entry.getKey() + ": OK");
  53.                 } else {
  54.                     System.err.println(entry.getKey() + ": FAIL, error message: " + entry.getValue().getMessage());
  55.                     final Throwable e = entry.getValue().getError();
  56.                     if (e != null) {
  57.                         e.printStackTrace();
  58.                     }
  59.                 }
  60.             }
  61.             try {
  62.                 Thread.sleep(1000);
  63.             } catch (InterruptedException e) {
  64.  
  65.             }
  66.         }
  67.     }
  68. }
  69.  
  70. /*
  71. console output:
  72. database1: OK
  73. database2: FAIL, error message: Can't ping database.
  74. database1: FAIL, error message: Can't ping database.
  75. database2: OK
  76. database1: OK
  77. database2: FAIL, error message: Can't ping database.
  78. database1: FAIL, error message: Can't ping database.
  79. database2: OK
  80. database1: FAIL, error message: Can't ping database.
  81. database2: FAIL, error message: Can't ping database.
  82. database1: FAIL, error message: Can't ping database.
  83. database2: FAIL, error message: Can't ping database.
  84. database1: OK
  85. database2: OK
  86. database1: OK
  87. database2: FAIL, error message: Can't ping database.
  88. database1: FAIL, error message: Can't ping database.
  89. database2: OK
  90. database1: OK
  91. database2: OK
  92. database1: FAIL, error message: Can't ping database.
  93. database2: OK
  94. database1: OK
  95. database2: OK
  96. database1: OK
  97. database2: OK
  98. database1: OK
  99. database2: FAIL, error message: Can't ping database.
  100. database1: FAIL, error message: Can't ping database.
  101. database2: FAIL, error message: Can't ping database.
  102.  
  103.  */

 

其他支持

metrics提供了对Ehcache、Apache HttpClient、JDBI、Jersey、Jetty、Log4J、Logback、JVM等的集成,可以方便地将Metrics输出到Ganglia、Graphite中,供用户图形化展示。

阅读全文……

标签 : ,



发表评论 发送引用通报