入门
本文将指导你将Metrics添加到现有你的程序中。 我们将介绍Metrics提供的各种测量仪器,如何使用它们以及什么时候它们会派上用场。
设置Maven
你需要metrics-core库作为依赖项:
<dependencies>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${metrics.version}</version>
</dependency>
</dependencies>
注意
确保在POM中使用当前版本(4.0.0)声明了一个metrics.version属性。
现在是时候为您的应用程序添加一些指标了!
Meters (度量)
仪表测量一段时间内的事件发生率(例如,“每秒请求数”)。 除了平均速率,仪表还可以跟踪1分钟,5分钟和15分钟的移动平均线。
private final MetricRegistry metrics = new MetricRegistry();
private final Meter requests = metrics.meter("requests");
public void handleRequest(Request request, Response response) {
requests.mark();
// etc
}
该仪表(meter)将测量每秒请求的请求率。
Console Reporter (控制台报告器)
控制台报告器(Console Reporter)就像它的名字一样,向控制台报告。将报告每秒打印一次。
ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter.start(1, TimeUnit.SECONDS);
完整的示例
所以完整的入门指南代码如下:
package sample;
import com.codahale.metrics.*;
import java.util.concurrent.TimeUnit;
public class GetStarted {
static final MetricRegistry metrics = new MetricRegistry();
public static void main(String args[]) {
startReport();
Meter requests = metrics.meter("requests");
requests.mark();
wait5Seconds();
}
static void startReport() {
ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter.start(1, TimeUnit.SECONDS);
}
static void wait5Seconds() {
try {
Thread.sleep(5*1000);
}
catch(InterruptedException e) {}
}
}
maven
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>somegroup</groupId>
<artifactId>sample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Example project for Metrics</name>
<dependencies>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${metrics.version}</version>
</dependency>
</dependencies>
</project>
注意
确保在POM中使用当前版本(4.0.0)声明了一个metrics.version属性。
最后运行:
mvn package exec:java -Dexec.mainClass=sample.GetStarted
Registry(注册)
Metrics的核心是MetricRegistry类,它是所有应用程序指标的容器。让我们先创建一个新的:
final MetricRegistry metrics = new MetricRegistry();
你可能希望将其集成到应用程序的生命周期中(可能使用您的依赖注入框架),但静态字段就很好。
Gauges(计量表)
gauge(计量器,又可称为仪表)是一个瞬时的测量值。 例如,我们可能想要测量队列中待处理作业的数量:
public class QueueManager {
private final Queue queue;
public QueueManager(MetricRegistry metrics, String name) {
this.queue = new Queue();
metrics.register(MetricRegistry.name(QueueManager.class, name, "size"),
new Gauge<Integer>() {
@Override
public Integer getValue() {
return queue.size();
}
});
}
}
测量此guage时,它将返回队列中的job数。
在registry中的每个指标都有一个唯一的名称,它只是一个点名字符串,如“things.count”或“com.example.Thing.latency”。 MetricRegistry有一个静态帮助方法来构造这个:
MetricRegistry.name(QueueManager.class, "jobs", "size")
这将返回一个类似“com.example.QueueManager.jobs.size”的字符串。
对于大多数队列和类似队列的结构,你当然不希望简单地返回queue.size()
。因为大多数java.util
和java.util.concurrent
都有#size()
的实现(如:O(n)
),这意味着你的计量器会很慢(可能有锁)。
Counters(计数器)
计数器只是AtomicLong实例。你可以递增或递减其值。例如,我们可能想要一种更有效的方法来测量队列中的待处理job:
private final Counter pendingJobs = metrics.counter(name(QueueManager.class, "pending-jobs"));
public void addJob(Job job) {
pendingJobs.inc();
queue.offer(job);
}
public Job takeJob() {
pendingJobs.dec();
return queue.take();
}
每次测量此计数器时,它将返回队列中的job数。
如您所见,计数器的API略有不同:#counter(String)
而不是#register(String,Metric)
。 虽然您可以使用register并创建自己的Counter实例,但#counter(String)
也可以完成所有工作,并允许您重用具有相同名称的metrics(度量、指标)。
此外,我们在此范围内静态导入MetricRegistry的名称方法以减少代码的复杂度。
Histograms(直方图;柱状图)
直方图测量数据流中值的统计分布。 除了最小值,最大值,平均值等,它还测量中位数,第75,90,95,98,99和99.9百分位数。
private final Histogram responseSizes = metrics.histogram(name(RequestHandler.class, "response-sizes"));
public void handleRequest(Request request, Response response) {
// etc
responseSizes.update(response.getContent().length);
}
该直方图测量响应的size以字节为单位。
Timers(定时器)
计时器测量特定代码段的调用速率和持续时间的分布。
private final Timer responses = metrics.timer(name(RequestHandler.class, "responses"));
public String handleRequest(Request request, Response response) {
final Timer.Context context = responses.time();
try {
// etc;
return "OK";
} finally {
context.stop();
}
}
此计时器将测量每个请求处理所需的时间(以纳秒为单位),并以每秒中请求提供请求速率。
Health Checks(健康验证)
Metrics还可以使用metrics-healthchecks模块集中对服务进行健康检查。
搜仙,创建一个HealthCheckRegistry
实例:
final HealthCheckRegistry healthChecks = new HealthCheckRegistry();
Second, implement a HealthCheck subclass:
public class DatabaseHealthCheck extends HealthCheck {
private final Database database;
public DatabaseHealthCheck(Database database) {
this.database = database;
}
@Override
public HealthCheck.Result check() throws Exception {
if (database.isConnected()) {
return HealthCheck.Result.healthy();
} else {
return HealthCheck.Result.unhealthy("Cannot connect to " + database.getUrl());
}
}
}
然后使用Metrics注册它的实例:
healthChecks.register("postgres", new DatabaseHealthCheck(database));
要运行所有已注册的运行状况检查:
final Map<String, HealthCheck.Result> results = healthChecks.runHealthChecks();
for (Entry<String, HealthCheck.Result> entry : results.entrySet()) {
if (entry.getValue().isHealthy()) {
System.out.println(entry.getKey() + " is healthy");
} else {
System.err.println(entry.getKey() + " is UNHEALTHY: " + entry.getValue().getMessage());
final Throwable e = entry.getValue().getError();
if (e != null) {
e.printStackTrace();
}
}
}
Metrics带有预先构建的健康检查:ThreadDeadlockHealthCheck,它使用Java的内置线程死锁检测来确定是否有任何线程死锁。
Reporting Via JMX(通过JMX报告)
要通过JMX报告指标,通过maven引入metrics-jmx
模块:
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-jmx</artifactId>
<version>${metrics.version}</version>
</dependency>
注意
确保在POM中使用当前版本(4.0.0)声明了metrics.version
属性。
final JmxReporter reporter = JmxReporter.forRegistry(registry).build();
reporter.start();
启动后,注册表中的所有指标都将通过JConsole或VisualVM显示(如果安装了MBeans插件):
Reporting Via HTTP(通过HTTP报告)
Metrics还附带一个servlet(AdminServlet)
,它将提供所有已注册metrics的JSON。它也运行了健康检查,输出出一个线程dump,并为负载均衡器提供简单的“ping”响应。 (还有单独的 servlet-MetricsServlet,HealthCheckServlet,ThreadDumpServlet和PingServlet -- 它们执行这些单独的任务。)
要使用servlet,要引入metrics-serlets模块:
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-servlets</artifactId>
<version>${metrics.version}</version>
</dependency>
确保在POM中使用当前版本(4.0.0)声明了metrics.version属性。
之后,你就可以将servlet映射到您认为合适的路径。
Other Reporting(其他的报告)
除了JMX和HTTP,Metrics还有以下输出报告:
STDOUT
, 使用metrics-core
的ConsoleReporterCSV
文件, 使用metrics-core
中的CsvReporter- SLF4J loggers, 使用metrics-core的Slf4jReporter
- Graphite, 使用来自metrics-graphite的GraphiteReporter