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

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. Break Standard Weight (ZOJ 3706)

    Problem The balance was the first mass measuring instrument invented. In its traditional form, it co ...

  2. python的协程,monkeyPatch

    monkey patch 一般指运行时候进行动态替换. 基本上我们使用gevent,会在最开头的地方加入gevent.monkey.patch_all();把标准库中的thread/socket等给替 ...

  3. [2]windows内核情景分析--系统调用

    Windows的地址空间分用户模式与内核模式,低2GB的部分叫用户模式,高2G的部分叫内核模式,位于用户空间的代码不能访问内核空间,位于内核空间的代码却可以访问用户空间 一个线程的运行状态分内核态与用 ...

  4. Vue2 响应式原理

    我们经常用vue的双向绑定,改变data的某个属性值,vue就马上帮我们自动更新视图,下面我们看看原理. Object的响应式原理: 可以看到,其实核心就是把object的所有属性都加上getter. ...

  5. 八、linux文件系统上的特殊权限 SUID 、GUID、Sticky

    安全上下文 前提:进程有属主和属组,文件有属主和属组 任何一个可执行程序文件能不能启动为进程:取决发起者对程序文件是否拥有执行权限 启动为进程之后,其进程的属主为发起者:进程的属组为发起者所属的组 进 ...

  6. springboot中web应用的统一异常处理

    在web应用中,请求处理过程中发生异常是非常常见的情况.springboot为我们提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异 ...

  7. Git LFS的使用

    Git LFS的使用 Git LFS 是 Github 开发的一个 Git 的扩展,用于实现 Git 对大文件的支持 使用目的 在游戏开发过程中,设计资源占用了很大一部分空间. 像png,psd等文件 ...

  8. vue实现购物清单列表添加删除

    vue实现购物清单列表添加删除 一.总结 一句话总结: 基础的v-model操作,以及数组的添加(push)删除(splice)操作 1.checkbox可以绑定数组,也可以直接绑定值? 绑定数组就是 ...

  9. $this->request->post 和input 区别

    $this->request->post 和input 区别 Request是对象,而input是内置函数     文章来源:刘俊涛的博客 欢迎关注,有问题一起学习欢迎留言.评论

  10. PHP学习之工厂方法模式

    <?php //工厂方法模式 interface Doing { function eat(); function sleep(); } class Cat implements Doing { ...