java metric_java版的Metric工具介绍
Metrics是一個(gè)給JAVA服務(wù)的各項(xiàng)指標(biāo)提供度量工具的包,在JAVA代碼中嵌入Metrics代碼,可以方便的對(duì)業(yè)務(wù)代碼的各個(gè)指標(biāo)進(jìn)行監(jiān)控,同時(shí),Metrics能夠很好的跟Ganlia、Graphite結(jié)合,方便的提供圖形化接口?;臼褂梅绞街苯訉ore包(目前穩(wěn)定版本3.0.1)導(dǎo)入pom文件即可,配置如下:
com.codahale.metricsgroupId> metrics-coreartifactId> 3.0.1version> dependency>
core包主要提供如下核心功能:
Metrics Registries類(lèi)似一個(gè)metrics容器,維護(hù)一個(gè)Map,可以是一個(gè)服務(wù)一個(gè)實(shí)例。
支持五種metric類(lèi)型:Gauges、Counters、Meters、Histograms和Timers。
可以將metrics值通過(guò)JMX、Console,CSV文件和SLF4J loggers發(fā)布出來(lái)。
五種Metrics類(lèi)型:
1.?????? Gauges
Gauges是一個(gè)最簡(jiǎn)單的計(jì)量,一般用來(lái)統(tǒng)計(jì)瞬時(shí)狀態(tài)的數(shù)據(jù)信息,比如系統(tǒng)中處于pending狀態(tài)的job。測(cè)試代碼
點(diǎn)擊(此處)折疊或打開(kāi)
package com.netease.test.metrics;
import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.JmxReporter;
import com.codahale.metrics.MetricRegistry;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
/**
* User: hzwangxx
* Date: 14-2-17
* Time: 14:47
* 測(cè)試Gauges,實(shí)時(shí)統(tǒng)計(jì)pending狀態(tài)的job個(gè)數(shù)
*/
public class TestGauges {
/**
* 實(shí)例化一個(gè)registry,最核心的一個(gè)模塊,相當(dāng)于一個(gè)應(yīng)用程序的metrics系統(tǒng)的容器,維護(hù)一個(gè)Map
*/
private static final MetricRegistry metrics = new MetricRegistry();
private static Queue queue = new LinkedBlockingDeque();
/**
* 在控制臺(tái)上打印輸出
*/
private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
public static void main(String[] args) throws InterruptedException {
reporter.start(3, TimeUnit.SECONDS);
//實(shí)例化一個(gè)Gauge
Gauge gauge = new Gauge() {
@Override
public Integer getValue() {
return queue.size();
}
};
//注冊(cè)到容器中
metrics.register(MetricRegistry.name(TestGauges.class, "pending-job", "size"), gauge);
//測(cè)試JMX
JmxReporter jmxReporter = JmxReporter.forRegistry(metrics).build();
jmxReporter.start();
//模擬數(shù)據(jù)
for (int i=0; i<20; i++){
queue.add("a");
Thread.sleep(1000);
}
}
}
/*
console output:
14-2-17 15:29:35 ===============================================================
-- Gauges ----------------------------------------------------------------------
com.netease.test.metrics.TestGauges.pending-job.size
value = 4
14-2-17 15:29:38 ===============================================================
-- Gauges ----------------------------------------------------------------------
com.netease.test.metrics.TestGauges.pending-job.size
value = 6
14-2-17 15:29:41 ===============================================================
-- Gauges ----------------------------------------------------------------------
com.netease.test.metrics.TestGauges.pending-job.size
value = 9
*/
通過(guò)以上步驟將會(huì)向MetricsRegistry容器中注冊(cè)一個(gè)名字為com.netease.test.metrics .TestGauges.pending-job.size的metrics,實(shí)時(shí)獲取隊(duì)列長(zhǎng)度的指標(biāo)。另外,Core包種還擴(kuò)展了幾種特定的Gauge:
JMX Gauges—提供給第三方庫(kù)只通過(guò)JMX將指標(biāo)暴露出來(lái)。
Ratio Gauges—簡(jiǎn)單地通過(guò)創(chuàng)建一個(gè)gauge計(jì)算兩個(gè)數(shù)的比值。
Cached Gauges—對(duì)某些計(jì)量指標(biāo)提供緩存
Derivative Gauges—提供Gauge的值是基于其他Gauge值的接口。
2.?????? Counter
Counter是Gauge的一個(gè)特例,維護(hù)一個(gè)計(jì)數(shù)器,可以通過(guò)inc()和dec()方法對(duì)計(jì)數(shù)器做修改。使用步驟與Gauge基本類(lèi)似,在MetricRegistry中提供了靜態(tài)方法可以直接實(shí)例化一個(gè)Counter。
點(diǎn)擊(此處)折疊或打開(kāi)
package com.netease.test.metrics;
import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.Counter;
import com.codahale.metrics.MetricRegistry;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
import static com.codahale.metrics.MetricRegistry.*;
/**
* User: hzwangxx
* Date: 14-2-14
* Time: 14:02
* 測(cè)試Counter
*/
public class TestCounter {
/**
* 實(shí)例化一個(gè)registry,最核心的一個(gè)模塊,相當(dāng)于一個(gè)應(yīng)用程序的metrics系統(tǒng)的容器,維護(hù)一個(gè)Map
*/
private static final MetricRegistry metrics = new MetricRegistry();
/**
* 在控制臺(tái)上打印輸出
*/
private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
/**
* 實(shí)例化一個(gè)counter,同樣可以通過(guò)如下方式進(jìn)行實(shí)例化再注冊(cè)進(jìn)去
* pendingJobs = new Counter();
* metrics.register(MetricRegistry.name(TestCounter.class, "pending-jobs"), pendingJobs);
*/
private static Counter pendingJobs = metrics.counter(name(TestCounter.class, "pedding-jobs"));
// private static Counter pendingJobs = metrics.counter(MetricRegistry.name(TestCounter.class, "pedding-jobs"));
private static Queue queue = new LinkedList();
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);
}
}
}
/*
console output:
14-2-17 17:52:34 ===============================================================
-- Counters --------------------------------------------------------------------
com.netease.test.metrics.TestCounter.pedding-jobs
count = 4
14-2-17 17:52:37 ===============================================================
-- Counters --------------------------------------------------------------------
com.netease.test.metrics.TestCounter.pedding-jobs
count = 6
14-2-17 17:52:40 ===============================================================
-- Counters --------------------------------------------------------------------
com.netease.test.metrics.TestCounter.pedding-jobs
count = 9
*/
3.?????? Meters
Meters用來(lái)度量某個(gè)時(shí)間段的平均處理次數(shù)(request per second),每1、5、15分鐘的TPS。比如一個(gè)service的請(qǐng)求數(shù),通過(guò)metrics.meter()實(shí)例化一個(gè)Meter之后,然后通過(guò)meter.mark()方法就能將本次請(qǐng)求記錄下來(lái)。統(tǒng)計(jì)結(jié)果有總的請(qǐng)求數(shù),平均每秒的請(qǐng)求數(shù),以及最近的1、5、15分鐘的平均TPS。
點(diǎn)擊(此處)折疊或打開(kāi)
package com.netease.test.metrics;
import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import java.util.concurrent.TimeUnit;
import static com.codahale.metrics.MetricRegistry.*;
/**
* User: hzwangxx
* Date: 14-2-17
* Time: 18:34
* 測(cè)試Meters
*/
public class TestMeters {
/**
* 實(shí)例化一個(gè)registry,最核心的一個(gè)模塊,相當(dāng)于一個(gè)應(yīng)用程序的metrics系統(tǒng)的容器,維護(hù)一個(gè)Map
*/
private static final MetricRegistry metrics = new MetricRegistry();
/**
* 在控制臺(tái)上打印輸出
*/
private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
/**
* 實(shí)例化一個(gè)Meter
*/
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);
}
}
}
/*
14-2-17 18:43:08 ===============================================================
-- Meters ----------------------------------------------------------------------
com.netease.test.metrics.TestMeters.request
count = 30
mean rate = 9.95 events/second
1-minute rate = 0.00 events/second
5-minute rate = 0.00 events/second
15-minute rate = 0.00 events/second
14-2-17 18:43:11 ===============================================================
-- Meters ----------------------------------------------------------------------
com.netease.test.metrics.TestMeters.request
count = 60
mean rate = 9.99 events/second
1-minute rate = 10.00 events/second
5-minute rate = 10.00 events/second
15-minute rate = 10.00 events/second
14-2-17 18:43:14 ===============================================================
-- Meters ----------------------------------------------------------------------
com.netease.test.metrics.TestMeters.request
count = 90
mean rate = 9.99 events/second
1-minute rate = 10.00 events/second
5-minute rate = 10.00 events/second
15-minute rate = 10.00 events/second
*/
4.?????? Histograms
Histograms主要使用來(lái)統(tǒng)計(jì)數(shù)據(jù)的分布情況,最大值、最小值、平均值、中位數(shù),百分比(75%、90%、95%、98%、99%和99.9%)。例如,需要統(tǒng)計(jì)某個(gè)頁(yè)面的請(qǐng)求響應(yīng)時(shí)間分布情況,可以使用該種類(lèi)型的Metrics進(jìn)行統(tǒng)計(jì)。具體的樣例代碼如下:
點(diǎn)擊(此處)折疊或打開(kāi)
package com.netease.test.metrics;
import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.MetricRegistry;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import static com.codahale.metrics.MetricRegistry.name;
/**
* User: hzwangxx
* Date: 14-2-17
* Time: 18:34
* 測(cè)試Histograms
*/
public class TestHistograms {
/**
* 實(shí)例化一個(gè)registry,最核心的一個(gè)模塊,相當(dāng)于一個(gè)應(yīng)用程序的metrics系統(tǒng)的容器,維護(hù)一個(gè)Map
*/
private static final MetricRegistry metrics = new MetricRegistry();
/**
* 在控制臺(tái)上打印輸出
*/
private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
/**
* 實(shí)例化一個(gè)Histograms
*/
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);
}
}
}
/*
14-2-17 19:39:11 ===============================================================
-- Histograms ------------------------------------------------------------------
com.netease.test.metrics.TestHistograms.random
count = 30
min = 1
max = 97
mean = 45.93
stddev = 29.12
median = 39.50
75% <= 71.00
95% <= 95.90
98% <= 97.00
99% <= 97.00
99.9% <= 97.00
14-2-17 19:39:14 ===============================================================
-- Histograms ------------------------------------------------------------------
com.netease.test.metrics.TestHistograms.random
count = 60
min = 0
max = 97
mean = 41.17
stddev = 28.60
median = 34.50
75% <= 69.75
95% <= 92.90
98% <= 96.56
99% <= 97.00
99.9% <= 97.00
14-2-17 19:39:17 ===============================================================
-- Histograms ------------------------------------------------------------------
com.netease.test.metrics.TestHistograms.random
count = 90
min = 0
max = 97
mean = 44.67
stddev = 28.47
median = 43.00
75% <= 71.00
95% <= 91.90
98% <= 96.18
99% <= 97.00
99.9% <= 97.00
*/
5.?????? Timers
Timers主要是用來(lái)統(tǒng)計(jì)某一塊代碼段的執(zhí)行時(shí)間以及其分布情況,具體是基于Histograms和Meters來(lái)實(shí)現(xiàn)的。樣例代碼如下:
點(diǎn)擊(此處)折疊或打開(kāi)
package com.netease.test.metrics;
import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import static com.codahale.metrics.MetricRegistry.name;
/**
* User: hzwangxx
* Date: 14-2-17
* Time: 18:34
* 測(cè)試Timers
*/
public class TestTimers {
/**
* 實(shí)例化一個(gè)registry,最核心的一個(gè)模塊,相當(dāng)于一個(gè)應(yīng)用程序的metrics系統(tǒng)的容器,維護(hù)一個(gè)Map
*/
private static final MetricRegistry metrics = new MetricRegistry();
/**
* 在控制臺(tái)上打印輸出
*/
private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
/**
* 實(shí)例化一個(gè)Meter
*/
// private static final Timer requests = metrics.timer(name(TestTimers.class, "request"));
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));
}
}
}
/*
14-2-18 9:31:54 ================================================================
-- Timers ----------------------------------------------------------------------
com.netease.test.metrics.TestTimers.request
count = 4
mean rate = 1.33 calls/second
1-minute rate = 0.00 calls/second
5-minute rate = 0.00 calls/second
15-minute rate = 0.00 calls/second
min = 483.07 milliseconds
max = 901.92 milliseconds
mean = 612.64 milliseconds
stddev = 196.32 milliseconds
median = 532.79 milliseconds
75% <= 818.31 milliseconds
95% <= 901.92 milliseconds
98% <= 901.92 milliseconds
99% <= 901.92 milliseconds
99.9% <= 901.92 milliseconds
14-2-18 9:31:57 ================================================================
-- Timers ----------------------------------------------------------------------
com.netease.test.metrics.TestTimers.request
count = 8
mean rate = 1.33 calls/second
1-minute rate = 1.40 calls/second
5-minute rate = 1.40 calls/second
15-minute rate = 1.40 calls/second
min = 41.07 milliseconds
max = 968.19 milliseconds
mean = 639.50 milliseconds
stddev = 306.12 milliseconds
median = 692.77 milliseconds
75% <= 885.96 milliseconds
95% <= 968.19 milliseconds
98% <= 968.19 milliseconds
99% <= 968.19 milliseconds
99.9% <= 968.19 milliseconds
14-2-18 9:32:00 ================================================================
-- Timers ----------------------------------------------------------------------
com.netease.test.metrics.TestTimers.request
count = 15
mean rate = 1.67 calls/second
1-minute rate = 1.40 calls/second
5-minute rate = 1.40 calls/second
15-minute rate = 1.40 calls/second
min = 41.07 milliseconds
max = 968.19 milliseconds
mean = 591.35 milliseconds
stddev = 302.96 milliseconds
median = 650.56 milliseconds
75% <= 838.07 milliseconds
95% <= 968.19 milliseconds
98% <= 968.19 milliseconds
99% <= 968.19 milliseconds
99.9% <= 968.19 milliseconds
*/
6 ?Health Checks
Metrics提供了一個(gè)獨(dú)立的模塊:Health Checks,用于對(duì)Application、其子模塊或者關(guān)聯(lián)模塊的運(yùn)行是否正常做檢測(cè)。該模塊是獨(dú)立metrics-core模塊的,使用時(shí)則導(dǎo)入metrics-healthchecks包。
com.codahale.metricsgroupId> metrics-healthchecksartifactId> 3.0.1version> dependency>
使用起來(lái)和與上述幾種類(lèi)型的Metrics有點(diǎn)類(lèi)似,但是需要重新實(shí)例化一個(gè)Metrics容器HealthCheckRegistry,待檢測(cè)模塊繼承抽象類(lèi)HealthCheck并實(shí)現(xiàn)check()方法即可,然后將該模塊注冊(cè)到HealthCheckRegistry中,判斷的時(shí)候通過(guò)isHealthy()接口即可。如下示例代碼:
點(diǎn)擊(此處)折疊或打開(kāi)
package com.netease.test.metrics;
import com.codahale.metrics.health.HealthCheck;
import com.codahale.metrics.health.HealthCheckRegistry;
import java.util.Map;
import java.util.Random;
/**
* User: hzwangxx
* Date: 14-2-18
* Time: 9:57
*/
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.");
}
/**
* 模擬Database對(duì)象
*/
static class Database {
/**
* 模擬database的ping方法
* @return 隨機(jī)返回boolean值
*/
public boolean ping() {
Random random = new Random();
return random.nextBoolean();
}
}
public static void main(String[] args) {
// MetricRegistry metrics = new MetricRegistry();
// ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();
HealthCheckRegistry registry = new HealthCheckRegistry();
registry.register("database1", new DatabaseHealthCheck(new Database()));
registry.register("database2", new DatabaseHealthCheck(new Database()));
while (true) {
for (Map.Entry 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) {
}
}
}
}
/*
console output:
database1: OK
database2: FAIL, error message: Can't ping database.
database1: FAIL, error message: Can't ping database.
database2: OK
database1: OK
database2: FAIL, error message: Can't ping database.
database1: FAIL, error message: Can't ping database.
database2: OK
database1: FAIL, error message: Can't ping database.
database2: FAIL, error message: Can't ping database.
database1: FAIL, error message: Can't ping database.
database2: FAIL, error message: Can't ping database.
database1: OK
database2: OK
database1: OK
database2: FAIL, error message: Can't ping database.
database1: FAIL, error message: Can't ping database.
database2: OK
database1: OK
database2: OK
database1: FAIL, error message: Can't ping database.
database2: OK
database1: OK
database2: OK
database1: OK
database2: OK
database1: OK
database2: FAIL, error message: Can't ping database.
database1: FAIL, error message: Can't ping database.
database2: FAIL, error message: Can't ping database.
*/
其他支持
metrics提供了對(duì)Ehcache、Apache HttpClient、JDBI、Jersey、Jetty、Log4J、Logback、JVM等的集成,可以方便地將Metrics輸出到Ganglia、Graphite中,供用戶圖形化展示。
總結(jié)
以上是生活随笔為你收集整理的java metric_java版的Metric工具介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 多变量微积分(4)——多重积分之三重积分
- 下一篇: java jml_JML 入门