Yammer Methrics入门

半兽人 发表于: 2019-02-20   最后更新时间: 2019-02-27 22:46:42  
{{totalSubscript}} 订阅, 3,158 游览

入门

本文将指导你将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.utiljava.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插件):

screenshot

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-coreConsoleReporter
  • CSV文件, 使用metrics-core中的CsvReporter
  • SLF4J loggers, 使用metrics-core的Slf4jReporter
  • Graphite, 使用来自metrics-graphite的GraphiteReporter
更新于 2019-02-27

查看YammerMetrics更多相关的文章或提一个关于YammerMetrics的问题,也可以与我们一起分享文章