在应用程序中,通常会记录日志以便事后分析,在很多情况下是产生了问题之后,再去查看日志,是一种事后的静态分析。在很多时候,我们可能需要了解整个系统在当前,或者某一时刻运行的情况,比如一个系统后台服务,我们可能需要了解一些实时监控的数据例如

1、每秒钟的请求数是多少(TPS)?

2、平均每个请求处理的时间?

3、请求处理的最长耗时?

4.请求处理的响应的直方图?

5、请求处理正确响应率?

6、等待处理的请求队列长度?

7、查看整个系统的的CPU使用率、内存占用、jvm运行情况;以及系统运行出错率等等一系列的实时数据采集时,最简单的方法就是在系统的入口、出口和关键位置设置埋点,然后将采集到的信息发送到实时监控平台或者存入到缓存和DB中做进一步的分析和展示。

Metrics作为一款监控指标的度量类库,提供了许多工具帮助开发者来完成各项数据的监控。

详见官方文档:https://metrics.dropwizard.io/3.1.0/manual/core/

一.Metrics 工具类库的介绍

  Metrics提供5种基本的度量类型:Meters Gauges  Counters   Histograms   Timers

  1.设置maven依赖 

<dependencies>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>3.2.6</version>
</dependency> <dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-healthchecks</artifactId>
<version>3.2.6</version>
</dependency>
</dependencies>

         2.Meters 的介绍与使用

//Meter(测量)是一种只能自增的计数器,通常用来度量一系列事件发生的概率。它提供了平均速率,以及指数平滑平均速率,以及采样后的1分钟,5分钟,15分钟的样例。
public class MetricsExample { //创建注册表
private final static MetricRegistry registry = new MetricRegistry(); //创建tps测量表
private final static Meter requestMeter = registry.meter("tps"); //创建异常测量表
private final static Meter errorMeter = registry.meter("err_request"); public static void main(String[] args) { //数据生成报告(按每分钟来统计)
ConsoleReporter report = ConsoleReporter.forRegistry(registry)
.convertRatesTo(TimeUnit.MINUTES)
.convertDurationsTo(TimeUnit.MINUTES)
.build();
report.start(10, TimeUnit.SECONDS); //每10秒将数据打印到控制台上 for(;;){   //模拟一直调用请求
getAsk();  //发送请求
randomSleep(); //间隔的发送请求
}
}
//处理请求方法
public static void getAsk(){
try {
requestMeter.mark();
randomSleep();
int x = 10/ThreadLocalRandom.current().nextInt(6);
} catch (Exception e) {
System.out.println("Error");
errorMeter.mark();
}
} //模拟处理请求耗时
public static void randomSleep(){
try {
TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(10)); //随机休眠时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//打印结果如下

19-6-4 16:38:47 ================================================================

-- Meters ----------------------------------------------------------------------
err_request
count = 1
mean rate = 1.50 events/minute
1-minute rate = 0.75 events/minute
5-minute rate = 0.19 events/minute
15-minute rate = 0.07 events/minute
tps
count = 4
mean rate = 5.99 events/minute
1-minute rate = 8.85 events/minute
5-minute rate = 11.24 events/minute
15-minute rate = 11.74 events/minute

3.gauge的介绍与使用

  3.1 gauge的使用

/**
* @des gauge的使用
* @author zhao
* @date 2019年6月14日上午12:08:02
* Gauge是一个最简单的计量,一般用来统计瞬时状态的数据信息
* 例:某一时刻的集合中的大小
*/
public class GaugeExample {   //定义度量中心
  private static MetricRegistry registry = new MetricRegistry();
  
  //定义队列
  private static Queue<Integer> queue = new LinkedBlockingQueue<>();
  
  public static void main(String[] args) throws InterruptedException {
    //将信息展示到控制台上
    ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build();
    reporter.start(3, TimeUnit.SECONDS);
    Gauge<Integer> gauge = new Gauge<Integer>() {
      @Override
      public Integer getValue() {
        return queue.size();
      }
    };
  //将定义过的gauge 注册到注册中心
  registry.register(MetricRegistry.name(GaugeExample.class, "queue-size"), gauge);
//模拟queue队列中的数据
  for (int i = 0; i < 100; i++) {
    queue.add(i); TimeUnit.MILLISECONDS.sleep(100);
  }
  Thread.currentThread().join();
  }
}
// 打印结果
19-6-14 0:39:17 ================================================================ -- Gauges ----------------------------------------------------------------------
com.zpb.gauge.GaugeExample.queue-size
value = 31 19-6-14 0:39:20 ================================================================ -- Gauges ----------------------------------------------------------------------
com.zpb.gauge.GaugeExample.queue-size
value = 60 19-6-14 0:39:23 ================================================================ -- Gauges ----------------------------------------------------------------------
com.zpb.gauge.GaugeExample.queue-size
value = 90

  3.2RatioGauge 的使用

    作用:度量事件成功率的计算。  例:度量缓存命中率、接口调用率等等。

public class RatioGaugeExample {

    private static MetricRegistry registry = new MetricRegistry();
private static Meter totalMeter = registry.meter("totalCount");
private static Meter succMeter = registry.meter("succCount"); public static void main(String[] args) {
ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build();
reporter.start(5, TimeUnit.SECONDS); //每5秒发送一次到控制台 registry.gauge("succ-ratio", ()-> new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(succMeter.getCount(),totalMeter.getCount()); //第一个参数:分子 第二个参数:分母
}
}); //调用
for(;;){
processHandle();
}
}
public static void processHandle(){
//total count
totalMeter.mark();
try {
int x = 10/ThreadLocalRandom.current().nextInt(10);
TimeUnit.MILLISECONDS.sleep(100);
//succ count
succMeter.mark();
} catch (Exception e) {
System.out.println("================ err");
}
}
}
//打印结果

19-6-17 9:28:13 ================================================================


-- Gauges ----------------------------------------------------------------------
succ-ratio
value = 0.9607843137254902


-- Meters ----------------------------------------------------------------------
succCount
count = 49
mean rate = 9.52 events/second
1-minute rate = 9.60 events/second
5-minute rate = 9.60 events/second
15-minute rate = 9.60 events/second
totalCount
count = 51
mean rate = 9.90 events/second
1-minute rate = 10.00 events/second
5-minute rate = 10.00 events/second
15-minute rate = 10.00 events/second


19-6-17 9:28:18 ================================================================


-- Gauges ----------------------------------------------------------------------
succ-ratio
value = 0.9423076923076923


-- Meters ----------------------------------------------------------------------
succCount
count = 98
mean rate = 9.71 events/second
1-minute rate = 9.63 events/second
5-minute rate = 9.61 events/second
15-minute rate = 9.60 events/second
totalCount
count = 104
mean rate = 10.31 events/second
1-minute rate = 10.06 events/second
5-minute rate = 10.01 events/second
15-minute rate = 10.00 events/second

4.Counter 的使用

  作用:Counter是Gauge的一个特例,维护一个计数器,可以通过inc()和dec()方法对计数器做修改。使用步骤与Gauge基本类似,在MetricRegistry中提供了静态方法可以直接实例化一个Counter。可以用来度量生产者和消费者之间的关系

public class CounterExample {

    private static final Logger  LOG = LoggerFactory.getLogger(CounterExample.class);

    //度量注册中心
private static final MetricRegistry registry = new MetricRegistry(); //度量计数器
private static final Counter counter = registry.counter(MetricRegistry.name(CounterExample.class, "")); private static final ConsoleReporter report = ConsoleReporter.forRegistry(registry)
.convertRatesTo(TimeUnit.MINUTES)
.convertDurationsTo(TimeUnit.MINUTES)
.build();
private static Queue<String> queue = new LinkedList<String>(); public static void main(String[] args) throws Exception { report.start(5, TimeUnit.SECONDS); //每5秒将数据打印到控制台上 new Thread(new Runnable() {
@Override
public void run() {
try {
production("abc");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();;
Thread.currentThread().join();
} public static void production(String s) throws InterruptedException{ for(int i = 0; i < 100;i++){
counter.inc();
queue.offer(s);
}
}
public static void consume() throws InterruptedException{
while(queue.size() != 0){
queue.poll(); //删除第1个元素
counter.dec(); }
}
}

5.Histograms直方图

  作用:主要使用来统计数据的分布情况, 最大值、最小值、平均值、中位数,百分比(75%、90%、95%、98%、99%和99.9%)。

  例如,需要统计某个页面的请求、接口方法请求的响应时间

public class HistogramsExample {

    private static final MetricRegistry registry = new MetricRegistry();

    private static ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build();

    //实例化一个Histograms
private static final Histogram histogram = registry.histogram(MetricRegistry.name(HistogramsExample.class,"histogram"));
public static void main(String[] args) throws InterruptedException { reporter.start(5, TimeUnit.SECONDS);
Random r = new Random();
while(true){
processHandle(r.nextDouble());
Thread.sleep(100);
}
} private static void processHandle(Double d){
histogram.update((int) (d*100)); //在应用中,需要统计的位置调用Histogram的update()方法。
} }

6.Timer的使用

  作用:统计请求的速率和处理时间

  例如:某接口的总在一定时间内的请求总数,平均处理时间

public class TimerExample {

    //创建度量中心
private static final MetricRegistry registry = new MetricRegistry(); //输出到控制台
private static final ConsoleReporter report = ConsoleReporter.forRegistry(registry).build(); //实例化timer
private static final Timer timer = registry.timer("request"); public static void main(String[] args) {
report.start(5, TimeUnit.SECONDS);
while(true){
handleRequest();
}
}
private static void handleRequest(){
Context time = timer.time();try {
Thread.sleep(500);       //模拟处理请求时间
} catch (Exception e) {
System.out.println("err");
}finally {
time.stop();            //每次执行完都会关闭
System.out.println("==== timer 已关闭");
}
}
}
// 打印结果
19-6-17 11:25:27 =============================================================== -- Histograms ------------------------------------------------------------------
com.zpb.histograms.HistogramsExample.histogram
count = 50              #总请求数
min = 0
max = 98              
mean = 53.14            #平均值
stddev = 27.04            #标准差
median = 50.00            #中间值
75% <= 78.00
95% <= 92.00
98% <= 94.00
99% <= 98.00
99.9% <= 98.00

7.HealthChecks 

  作用:健康检查,用于对系统应用、子模块、关联模块的运行是否正常做检测

  实现过程:

    类A:继承 HealthCheck ,并重写check()方法 ,在check()中调用类B中的被检测方法

    类B:定义一个方法,返回结果是boolean类型。(类B也可以是其它系统中的一个类)

  

public class HealthChecksExample extends HealthCheck{

    private DataBase database;

    public HealthChecksExample(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{
//模拟ping方法
public boolean ping(){
Random r = new Random();
return r.nextBoolean();
}
} public static void main(String[] args) {
//创建健康检查注册中心
HealthCheckRegistry registry = new HealthCheckRegistry();
//将被检查的类注册到中心
     registry.register("database1",new HealthChecksExample(new DataBase()));
registry.register("database2", new HealthChecksExample(new DataBase()));
     //从运行的健康检查注册中心获取被检测的结果
Set<Entry<String, Result>> entrySet = registry.runHealthChecks().entrySet();
while(true){
for(Entry<String, Result> entry : 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 (Exception e) {
e.printStackTrace();
}
} }
} //打印结果

database1FAIL:error message: Can't ping database.
database2: OK
database1FAIL:error message: Can't ping database.
database2: OK
database1FAIL:error message: Can't ping database.
database2: OK

二.report 报告

  如上例子所示,我们拿到了很多类型的数据,但我们不能展示到控制台上,因此我们需要将数据导出,做成可展示的报告,在官网上有很多种类型的report,这里只介绍在工作中经常使用到的。

  将数据写到log日志中

  将日志通过logback写入到日志中,具体使用配置过程详见:loback的介绍与配置-(通俗易通)

  1.Timer 将数据写入log中
  

public class TimerExample {

    //创建度量中心
private static final MetricRegistry registry = new MetricRegistry(); //输出到日志文件中
private static final Slf4jReporter report = Slf4jReporter.forRegistry(registry)
.outputTo(LoggerFactory.getLogger("com.metrics.timer")) //定义该日志写到哪个包,这个你可以随意定义,但要与logback.xml中的logger中name一致即可
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.SECONDS)
.build();
//实例化timer
private static final Timer timer = registry.timer("request"); public static void main(String[] args) {
report.start(5, TimeUnit.SECONDS);
while(true){
handleRequest();
}
}
private static void handleRequest(){
Context time = timer.time();
try {
Thread.sleep(500);;         //模拟处理请求时间
} catch (Exception e) {
System.out.println("err ="+e);
}finally {
time.stop(); //一定要写finally,每次执行完都会关闭
System.out.println("==== timer 已关闭");
}
}
}

2.Counter将数据写入到日志中

public class CounterExample {

    private static final Logger  LOG = LoggerFactory.getLogger(CounterExample.class);

    //度量注册中心
private static final MetricRegistry registry = new MetricRegistry(); //度量计数器
private static final Counter counter = registry.counter(MetricRegistry.name(CounterExample.class, "")); //通过logback打印到日志文件上
private static final Slf4jReporter reporter = Slf4jReporter.forRegistry(registry)
.outputTo(LoggerFactory.getLogger("com.metrics"))
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.SECONDS)
.build();
private static Queue<String> queue = new LinkedList<String>(); public static void main(String[] args) throws Exception { reporter.start(5, TimeUnit.SECONDS);   //每5秒钟写一次日志

     new Thread(new Runnable() {
@Override
public void run() {
try {
production("abc");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();;
Thread.currentThread().join();
} public static void production(String s) throws InterruptedException{ for(int i = 0; i < 100;i++){
counter.inc();
queue.offer(s);
System.out.println("------- 生产 ----------->"+queue.size());
}
}
public static void consume() throws InterruptedException{
while(queue.size() != 0){
queue.poll(); //删除第1个元素
counter.dec();
System.err.println("<------- 消费 ----------- "+queue.size());
}
}
}

metrics for spring https://blog.csdn.net/woshibigsail/article/details/95341831

什么是Metrics-(通俗易懂)的更多相关文章

  1. 使用Metrics.NET 构建 ASP.NET MVC 应用程序的性能指标

    通常我们需要监测ASP.NET MVC 或 Web API 的应用程序的性能时,通常采用的是自定义性能计数器,性能计数器会引发无休止的运维问题(损坏的计数器.权限问题等).这篇文章向你介绍一个新的替代 ...

  2. 使用Metrics监控应用程序的性能

    在编写应用程序的时候,通常会记录日志以便事后分析,在很多情况下是产生了问题之后,再去查看日志,是一种事后的静态分析.在很多时候,我们可能需要了解整个系统在当前,或者某一时刻运行的情况,比如当前系统中对 ...

  3. 三维网格精简算法(Quadric Error Metrics)附源码

    在计算机图形应用中,为了尽可能真实呈现虚拟物体,往往需要高精度的三维模型.然而,模型的复杂性直接关系到它的计算成本,因此高精度的模型在几何运算时并不是必须的,取而代之的是一个相对简化的三维模型,那么如 ...

  4. Metrics.NET 项目

    Metrics.NET(https://github.com/etishor/Metrics.NET)是一个给CLR 提供度量工具的包,它是移植自Java的metrics,在c#代码中嵌入Metric ...

  5. 【转】能否用讲个故事的方式,由浅入深,通俗易懂地解释一下什么是天使投资,VC,PE.

    能否用讲个故事的方式,由浅入深,通俗易懂地解释一下什么是天使投资,VC,PE 今天在知乎上看到一篇文章,觉得值得一转的,Here. 我给楼主讲个完整点的故事吧.长文慎点,前方高能,自备避雷针.18岁以 ...

  6. python装饰器通俗易懂的解释!

    1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...

  7. 关于一个通俗易懂的FFT的C语言实现教程

    找到一个通俗易懂并且神奇并且有趣的FFT算法C语言实现教程:http://www.katjaas.nl/FFTimplement/FFTimplement.html 只要对矩阵比较熟悉就能在教程的辅助 ...

  8. Jmeter plugin jp@gc - PerfMon Metrics Collector

    Jmeter由于是开源工具,所以目前有很多插件可以供使用,最简单的方法是先把Plugin Manager安装了 下载地址:https://jmeter-plugins.org/wiki/Plugins ...

  9. 【原创】Kakfa metrics包源代码分析

    这个包主要是与Kafka度量相关的. 一.KafkaTimer.scala 对代码块的运行进行计时.仅提供一个方法: timer——在运行传入函数f的同时为期计时 二.KafkaMetricsConf ...

  10. Metrics介绍

    Metrics可以为你的代码的运行提供无与伦比的洞察力.作为一款监控指标的度量类库,它提供了很多模块可以为第三方库或者应用提供辅助统计信息, 比如Jetty, Logback, Log4j, Apac ...

随机推荐

  1. 转:关于C++ const 的全面总结

    转自:https://www.cnblogs.com/xkfz007/articles/2419518.html    如有侵权请联系博主,立即删除. C++中的const关键字的用法非常灵活,而使用 ...

  2. JS 的 new 到底是干什么的?

    大部分讲 new 的文章会从面向对象的思路讲起,但是我始终认为,在解释一个事物的时候,不应该引入另一个更复杂的事物. 今天我从「省代码」的角度来讲 new. --------------------- ...

  3. npm传参技巧

    博主今天遇到一个问题,使用vue-cli-serve,想要用shelljs来执行vue-cli-serve,动态给它传“--port xxxx"但是发现”--port“怎么传都穿不进去,后面 ...

  4. Js 之将html转为图片html2canvas

    一.效果图 二.代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  5. python 库 imgaug数据增强

    安装及详细使用方法介绍: https://blog.csdn.net/qq_38451119/article/details/82428612 pip install imgaug 失败解决方法: 提 ...

  6. PHP学习之分页类

    <?php $page = new Page(2, 40); var_dump($page->allUrl()); class Page { //每页显示多少条数据 protected $ ...

  7. Linunx创建软连接、删除软连接、修改软连接

    创建: ln -s [目标目录] [软链接地址] ln -s /usr/local/python3/bin/python3 /usr/bin/python3ln -s /usr/local/pytho ...

  8. Netty解码器相关文章

    最通用TCP黏包解决方案:LengthFieldBasedFrameDecoder和LengthFieldPrepender https://blog.csdn.net/u010853261/arti ...

  9. 免费下载 SetupVPN CRX 3.7.0 for Chrome OR QQ浏览器

    免费下载 SetupVPN CRX 3.7.0 for Chrome OR QQ浏览器 Lifetime Free VPN(微劈嗯) 下载setupvpn 3.7.0的crx文件, 打开chrome的 ...

  10. kotlin 之单表达式函数

    fun d(x:Int):Int=x* 如果函数体只有一条语句,而且是return语句,那么可以省略大括号以及return关键字,