什么是Metrics-(通俗易懂)
在应用程序中,通常会记录日志以便事后分析,在很多情况下是产生了问题之后,再去查看日志,是一种事后的静态分析。在很多时候,我们可能需要了解整个系统在当前,或者某一时刻运行的情况,比如一个系统后台服务,我们可能需要了解一些实时监控的数据例如
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的介绍与配置-(通俗易通)
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-(通俗易懂)的更多相关文章
- 使用Metrics.NET 构建 ASP.NET MVC 应用程序的性能指标
通常我们需要监测ASP.NET MVC 或 Web API 的应用程序的性能时,通常采用的是自定义性能计数器,性能计数器会引发无休止的运维问题(损坏的计数器.权限问题等).这篇文章向你介绍一个新的替代 ...
- 使用Metrics监控应用程序的性能
在编写应用程序的时候,通常会记录日志以便事后分析,在很多情况下是产生了问题之后,再去查看日志,是一种事后的静态分析.在很多时候,我们可能需要了解整个系统在当前,或者某一时刻运行的情况,比如当前系统中对 ...
- 三维网格精简算法(Quadric Error Metrics)附源码
在计算机图形应用中,为了尽可能真实呈现虚拟物体,往往需要高精度的三维模型.然而,模型的复杂性直接关系到它的计算成本,因此高精度的模型在几何运算时并不是必须的,取而代之的是一个相对简化的三维模型,那么如 ...
- Metrics.NET 项目
Metrics.NET(https://github.com/etishor/Metrics.NET)是一个给CLR 提供度量工具的包,它是移植自Java的metrics,在c#代码中嵌入Metric ...
- 【转】能否用讲个故事的方式,由浅入深,通俗易懂地解释一下什么是天使投资,VC,PE.
能否用讲个故事的方式,由浅入深,通俗易懂地解释一下什么是天使投资,VC,PE 今天在知乎上看到一篇文章,觉得值得一转的,Here. 我给楼主讲个完整点的故事吧.长文慎点,前方高能,自备避雷针.18岁以 ...
- python装饰器通俗易懂的解释!
1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...
- 关于一个通俗易懂的FFT的C语言实现教程
找到一个通俗易懂并且神奇并且有趣的FFT算法C语言实现教程:http://www.katjaas.nl/FFTimplement/FFTimplement.html 只要对矩阵比较熟悉就能在教程的辅助 ...
- Jmeter plugin jp@gc - PerfMon Metrics Collector
Jmeter由于是开源工具,所以目前有很多插件可以供使用,最简单的方法是先把Plugin Manager安装了 下载地址:https://jmeter-plugins.org/wiki/Plugins ...
- 【原创】Kakfa metrics包源代码分析
这个包主要是与Kafka度量相关的. 一.KafkaTimer.scala 对代码块的运行进行计时.仅提供一个方法: timer——在运行传入函数f的同时为期计时 二.KafkaMetricsConf ...
- Metrics介绍
Metrics可以为你的代码的运行提供无与伦比的洞察力.作为一款监控指标的度量类库,它提供了很多模块可以为第三方库或者应用提供辅助统计信息, 比如Jetty, Logback, Log4j, Apac ...
随机推荐
- 008_linuxC++之_类的静态变量和静态函数
(一)看程序 #include <iostream> #include <string.h> #include <unistd.h> using namespace ...
- mysql慢查询日志查找与分析
mysql下执行SHOW VARIABLES LIKE '%slow_query_log%' 上图我这是本地的mysql,慢查询没开. slow_query_log :ON和OFF分别表示慢查询有没有 ...
- 百度ueditor中复制word图文时图片转存任然保持灰色不可用
官网地址http://ueditor.baidu.com Git 地址 https://github.com/fex-team/ueditor 参考博客地址 http://blog.ncmem.com ...
- re匹配 [\s\S][\w\W]的使用.
本来想提取一个字符串写了一堆正则都提取不出来. 因为有特殊字符 后来使用 [\s\S]* 或 [\w\W]* 匹配出来. \s 空白字符 [ \t\n\r\f\v] \S 非空白字符 相当于 [^ \ ...
- vue怎么引入echats并使用 (柱状图 字符云)
安装 npm install echarts --save 下面看一下如何简单的使用: 在main.js中引入(全局引入) // 引入echarts import echarts from 'echa ...
- JVM——垃圾回收
目录: 如何判断垃圾是否回收? 引用计数法 可达性分析算法 四种引用 引用队列 垃圾回收算法 标记清除算法 复制算法 标记整理算法 分代垃圾回收 新生代 老年代 Minor GC 和 Full GC的 ...
- oracle查询消耗服务器资源SQL语句
1.查找最近一天内,最消耗CPU的SQL语句 SELECT ASH.INST_ID, ASH.SQL_ID, (SELECT VS.SQL_TEXT FROM GV$SQLAREA VS WHERE ...
- CF1195B
CF1195B 题意: 有一个盒子,每次可以做两个操作: 1.每次吃掉一块蛋糕 2.每次放入比上一次放入数多1的蛋糕 当盒子为空时,只能执行第 $ 2 $ 个操作.第 $ 1 $ 次操作永远是放入一个 ...
- 什么是Servlet容器?
在本文中,我写了一些关于Web服务器.Servlet容器以及它与JVM的关系的基本概念.我想表达的是,Servlet容器也仅仅不过是一个Java程序. 1. 什么是Web服务器? 想要知道什么是Ser ...
- 关于axios如何在请求头添加参数
vm.$http.post(apiUrl.refundOrder, data,{ headers:{ 'lz-shopid':vm.orderRecords.shopId } }).then(res ...