Dropwizardメトリクスの概要

1.はじめに

Metricsは、Javaアプリケーション用の測定機器を提供するJavaライブラリです。

いくつかのモジュールがあります。この記事では、参考のために、metrics-coreモジュール、metrics-healthchecksモジュール、metrics-servletsモジュール、metrics-servletモジュールについて詳しく説明し、残りをスケッチします。

2.モジュールメトリック-コア

2.1。Mavenの依存関係

metrics-coreモジュールを使用するには、pom.xmlファイルに追加する必要がある依存関係は1つだけです。

 io.dropwizard.metrics metrics-core 3.1.2  

そして、あなたはここでその最新バージョンを見つけることができます。

2.2。MetricRegistry

簡単に言うと、MetricRegistryクラスを使用して、1つまたは複数のメトリックを登録します。

すべてのメトリックに1つのメトリックレジストリを使用できますが、メトリックごとに異なるレポート方法を使用する場合は、メトリックをグループに分割し、グループごとに異なるメトリックレジストリを使用することもできます。

今すぐMetricRegistryを作成しましょう:

MetricRegistry metricRegistry = new MetricRegistry();

そして、このMetricRegistryにいくつかのメトリックを登録できます。

Meter meter1 = new Meter(); metricRegistry.register("meter1", meter1); Meter meter2 = metricRegistry.meter("meter2"); 

新しいメトリックを作成するには、2つの基本的な方法があります。自分でインスタンス化する方法と、メトリックレジストリから取得する方法です。ご覧のとおり、上記の例では両方を使用し、Meterオブジェクト「meter1」をインスタンス化し、metricRegistryによって作成された別のMeterオブジェクト「meter2」を取得しています。

上記のメトリック名として「meter1」と「meter2」を使用したため、メトリックレジストリでは、すべてのメトリックに一意の名前が付けられます。MetricRegistryは、適切なメトリック名を作成するのに役立つ一連の静的ヘルパーメソッドも提供します。

String name1 = MetricRegistry.name(Filter.class, "request", "count"); String name2 = MetricRegistry.name("CustomFilter", "response", "count"); 

一連のメトリックレジストリを管理する必要がある場合は、シングルトンでスレッドセーフなSharedMetricRegistriesクラスを使用できます。メトリックレジスタを追加し、そこからこのメトリックレジスタを取得して、削除することができます。

SharedMetricRegistries.add("default", metricRegistry); MetricRegistry retrievedMetricRegistry = SharedMetricRegistries.getOrCreate("default"); SharedMetricRegistries.remove("default"); 

3.メトリクスの概念

メトリックコアモジュールは、一般的に使用されるいくつかのメトリックタイプを提供します。メーターゲージカウンターヒストグラムタイマー、およびメトリックの値を出力するレポーターです

3.1。メーター

Aメーターは、イベントの発生をカウントし、レート測定します:

Meter meter = new Meter(); long initCount = meter.getCount(); assertThat(initCount, equalTo(0L)); meter.mark(); assertThat(meter.getCount(), equalTo(1L)); meter.mark(20); assertThat(meter.getCount(), equalTo(21L)); double meanRate = meter.getMeanRate(); double oneMinRate = meter.getOneMinuteRate(); double fiveMinRate = meter.getFiveMinuteRate(); double fifteenMinRate = meter.getFifteenMinuteRate(); 

同様にgetCount()メソッドの戻りイベントの発生をカウントし、マーク()メソッドは、イベントの発生回数1またはNを増大させます。メーターのオブジェクトは、全体の平均レートを表す4つの料金を提供してメーターをそれぞれ、最近5分間および最近の四半期の、最近1分間、寿命を。

3.2。ゲージ

ゲージは、特定の値を返すために単に使用されるインターフェースです。:メトリクスコアモジュールは、それのいくつかの実装提供RatioGaugeCachedGaugeDerivativeGaugeJmxAttributeGaugeを

RatioGaugeは抽象クラスであり、ある値と別の値の比率を測定します。

使い方を見てみましょう。まず、クラスAttendanceRatioGaugeを実装します。

public class AttendanceRatioGauge extends RatioGauge { private int attendanceCount; private int courseCount; @Override protected Ratio getRatio() { return Ratio.of(attendanceCount, courseCount); } // standard constructors } 

そしてそれをテストします:

RatioGauge ratioGauge = new AttendanceRatioGauge(15, 20); assertThat(ratioGauge.getValue(), equalTo(0.75)); 

CachedGaugeは、値をキャッシュできる別の抽象クラスであるため、値の計算にコストがかかる場合に非常に役立ちます。これを使用するには、クラスActiveUsersGaugeを実装する必要があります

public class ActiveUsersGauge extends CachedGauge
    
      { @Override protected List loadValue() { return getActiveUserCount(); } private List getActiveUserCount() { List result = new ArrayList(); result.add(12L); return result; } // standard constructors }
    

次に、それをテストして、期待どおりに機能するかどうかを確認します。

Gauge
    
      activeUsersGauge = new ActiveUsersGauge(15, TimeUnit.MINUTES); List expected = new ArrayList(); expected.add(12L); assertThat(activeUsersGauge.getValue(), equalTo(expected)); 
    

ActiveUsersGaugeをインスタンス化するときに、キャッシュの有効期限を15分に設定します。

DerivativeGaugeも抽象クラスであり、他のGaugeから値をその値として導出できます。

例を見てみましょう:

public class ActiveUserCountGauge extends DerivativeGauge
    
      { @Override protected Integer transform(List value) { return value.size(); } // standard constructors }
    

このゲージActiveUsersGaugeから値を取得するため、基本リストのサイズからの値であると予想されます。

Gauge
    
      activeUsersGauge = new ActiveUsersGauge(15, TimeUnit.MINUTES); Gauge activeUserCountGauge = new ActiveUserCountGauge(activeUsersGauge); assertThat(activeUserCountGauge.getValue(), equalTo(1)); 
    

JmxAttributeGaugeは、JMXを介して公開されている他のライブラリのメトリックにアクセスする必要がある場合に使用されます。

3.3。カウンター

カウンターはincrementationsとdecrementationsを記録するために使用されます。

Counter counter = new Counter(); long initCount = counter.getCount(); assertThat(initCount, equalTo(0L)); counter.inc(); assertThat(counter.getCount(), equalTo(1L)); counter.inc(11); assertThat(counter.getCount(), equalTo(12L)); counter.dec(); assertThat(counter.getCount(), equalTo(11L)); counter.dec(6); assertThat(counter.getCount(), equalTo(5L));

3.4。ヒストグラム

ヒストグラムは、Long値のストリームを追跡するために使用され、最大、最小、平均、中央値、標準偏差、75パーセンタイルなどの統計的特性を分析します。

Histogram histogram = new Histogram(new UniformReservoir()); histogram.update(5); long count1 = histogram.getCount(); assertThat(count1, equalTo(1L)); Snapshot snapshot1 = histogram.getSnapshot(); assertThat(snapshot1.getValues().length, equalTo(1)); assertThat(snapshot1.getValues()[0], equalTo(5L)); histogram.update(20); long count2 = histogram.getCount(); assertThat(count2, equalTo(2L)); Snapshot snapshot2 = histogram.getSnapshot(); assertThat(snapshot2.getValues().length, equalTo(2)); assertThat(snapshot2.getValues()[1], equalTo(20L)); assertThat(snapshot2.getMax(), equalTo(20L)); assertThat(snapshot2.getMean(), equalTo(12.5)); assertEquals(10.6, snapshot2.getStdDev(), 0.1); assertThat(snapshot2.get75thPercentile(), equalTo(20.0)); assertThat(snapshot2.get999thPercentile(), equalTo(20.0)); 

Histogram samples the data by using reservoir sampling, and when we instantiate a Histogram object, we need to set its reservoir explicitly.

Reservoir is an interface and metrics-core provides four implementations of them: ExponentiallyDecayingReservoir, UniformReservoir, SlidingTimeWindowReservoir, SlidingWindowReservoir.

In the section above, we mentioned that a metric can also be created by MetricRegistry, besides using a constructor. When we use metricRegistry.histogram(), it returns a Histogram instance with ExponentiallyDecayingReservoir implementation.

3.5. Timer

Timer is used for keeping track of multiple timing durations which are represented by Context objects, and it also provides their statistical data:

Timer timer = new Timer(); Timer.Context context1 = timer.time(); TimeUnit.SECONDS.sleep(5); long elapsed1 = context1.stop(); assertEquals(5000000000L, elapsed1, 1000000); assertThat(timer.getCount(), equalTo(1L)); assertEquals(0.2, timer.getMeanRate(), 0.1); Timer.Context context2 = timer.time(); TimeUnit.SECONDS.sleep(2); context2.close(); assertThat(timer.getCount(), equalTo(2L)); assertEquals(0.3, timer.getMeanRate(), 0.1); 

3.6. Reporter

When we need to output our measurements, we can use Reporter. This is an interface, and the metrics-core module provides several implementations of it, such as ConsoleReporter, CsvReporter, Slf4jReporter, JmxReporter and so on.

Here we use ConsoleReporter as an example:

MetricRegistry metricRegistry = new MetricRegistry(); Meter meter = metricRegistry.meter("meter"); meter.mark(); meter.mark(200); Histogram histogram = metricRegistry.histogram("histogram"); histogram.update(12); histogram.update(17); Counter counter = metricRegistry.counter("counter"); counter.inc(); counter.dec(); ConsoleReporter reporter = ConsoleReporter.forRegistry(metricRegistry).build(); reporter.start(5, TimeUnit.MICROSECONDS); reporter.report(); 

Here is the sample output of the ConsoleReporter:

-- Histograms ------------------------------------------------------------------ histogram count = 2 min = 12 max = 17 mean = 14.50 stddev = 2.50 median = 17.00 75% <= 17.00 95% <= 17.00 98% <= 17.00 99% <= 17.00 99.9% <= 17.00 -- Meters ---------------------------------------------------------------------- meter count = 201 mean rate = 1756.87 events/second 1-minute rate = 0.00 events/second 5-minute rate = 0.00 events/second 15-minute rate = 0.00 events/second 

4. Module metrics-healthchecks

Metrics has an extension metrics-healthchecks module for dealing with health checks.

4.1. Maven Dependencies

To use the metrics-healthchecks module, we need to add this dependency to the pom.xml file:

 io.dropwizard.metrics metrics-healthchecks 3.1.2 

And you can find its latest version here.

4.2. Usage

First, we need several classes which are responsible for specific health check operations, and these classes must implement HealthCheck.

For example, we use DatabaseHealthCheck and UserCenterHealthCheck:

public class DatabaseHealthCheck extends HealthCheck { @Override protected Result check() throws Exception { return Result.healthy(); } } 
public class UserCenterHealthCheck extends HealthCheck { @Override protected Result check() throws Exception { return Result.healthy(); } } 

Then, we need a HealthCheckRegistry (which is just like MetricRegistry), and register the DatabaseHealthCheck and UserCenterHealthCheck with it:

HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry(); healthCheckRegistry.register("db", new DatabaseHealthCheck()); healthCheckRegistry.register("uc", new UserCenterHealthCheck()); assertThat(healthCheckRegistry.getNames().size(), equalTo(2)); 

We can also unregister the HealthCheck:

healthCheckRegistry.unregister("uc"); assertThat(healthCheckRegistry.getNames().size(), equalTo(1)); 

We can run all the HealthCheck instances:

Map results = healthCheckRegistry.runHealthChecks(); for (Map.Entry entry : results.entrySet()) { assertThat(entry.getValue().isHealthy(), equalTo(true)); } 

Finally, we can run a specific HealthCheck instance:

healthCheckRegistry.runHealthCheck("db"); 

5. Module metrics-servlets

Metrics provides us a handful of useful servlets which allow us to access metrics related data through HTTP requests.

5.1. Maven Dependencies

To use the metrics-servlets module, we need to add this dependency to the pom.xml file:

 io.dropwizard.metrics metrics-servlets 3.1.2 

And you can find its latest version here.

5.2. HealthCheckServlet Usage

HealthCheckServlet provides health check results. First, we need to create a ServletContextListener which exposes our HealthCheckRegistry:

public class MyHealthCheckServletContextListener extends HealthCheckServlet.ContextListener { public static HealthCheckRegistry HEALTH_CHECK_REGISTRY = new HealthCheckRegistry(); static { HEALTH_CHECK_REGISTRY.register("db", new DatabaseHealthCheck()); } @Override protected HealthCheckRegistry getHealthCheckRegistry() { return HEALTH_CHECK_REGISTRY; } } 

Then, we add both this listener and HealthCheckServlet into the web.xml file:

 com.baeldung.metrics.servlets.MyHealthCheckServletContextListener   healthCheck com.codahale.metrics.servlets.HealthCheckServlet   healthCheck /healthcheck 

Now we can start the web application, and send a GET request to “//localhost:8080/healthcheck” to get health check results. Its response should be like this:

{ "db": { "healthy": true } }

5.3. ThreadDumpServlet Usage

ThreadDumpServlet provides information about all live threads in the JVM, their states, their stack traces, and the state of any locks they may be waiting for.

If we want to use it, we simply need to add these into the web.xml file:

 threadDump com.codahale.metrics.servlets.ThreadDumpServlet   threadDump /threaddump 

Thread dump data will be available at “//localhost:8080/threaddump”.

5.4. PingServlet Usage

PingServlet can be used to test if the application is running. We add these into the web.xml file:

 ping com.codahale.metrics.servlets.PingServlet   ping /ping 

And then send a GET request to “//localhost:8080/ping”. The response's status code is 200 and its content is “pong”.

5.5. MetricsServlet Usage

MetricsServlet provides metrics data. First, we need to create a ServletContextListener which exposes our MetricRegistry:

public class MyMetricsServletContextListener extends MetricsServlet.ContextListener { private static MetricRegistry METRIC_REGISTRY = new MetricRegistry(); static { Counter counter = METRIC_REGISTRY.counter("m01-counter"); counter.inc(); Histogram histogram = METRIC_REGISTRY.histogram("m02-histogram"); histogram.update(5); histogram.update(20); histogram.update(100); } @Override protected MetricRegistry getMetricRegistry() { return METRIC_REGISTRY; } } 

Both this listener and MetricsServlet need to be added into web.xml:

 com.codahale.metrics.servlets.MyMetricsServletContextListener   metrics com.codahale.metrics.servlets.MetricsServlet   metrics /metrics 

This will be exposed in our web application at “//localhost:8080/metrics”. Its response should contain various metrics data:

{ "version": "3.0.0", "gauges": {}, "counters": { "m01-counter": { "count": 1 } }, "histograms": { "m02-histogram": { "count": 3, "max": 100, "mean": 41.66666666666666, "min": 5, "p50": 20, "p75": 100, "p95": 100, "p98": 100, "p99": 100, "p999": 100, "stddev": 41.69998667732268 } }, "meters": {}, "timers": {} } 

5.6. AdminServlet Usage

AdminServlet aggregates HealthCheckServlet, ThreadDumpServlet, MetricsServlet, and PingServlet.

Let's add these into the web.xml:

 admin com.codahale.metrics.servlets.AdminServlet   admin /admin/* 

It can now be accessed at “//localhost:8080/admin”. We will get a page containing four links, one for each of those four servlets.

Note that, if we want to do health check and access metrics data, those two listeners are still needed.

6. Module metrics-servlet

The metrics-servlet module provides a Filter which has several metrics: meters for status codes, a counter for the number of active requests, and a timer for request duration.

6.1. Maven Dependencies

To use this module, let's first add the dependency into the pom.xml:

 io.dropwizard.metrics metrics-servlet 3.1.2 

And you can find its latest version here.

6.2. Usage

To use it, we need to create a ServletContextListener which exposes our MetricRegistry to the InstrumentedFilter:

public class MyInstrumentedFilterContextListener extends InstrumentedFilterContextListener { public static MetricRegistry REGISTRY = new MetricRegistry(); @Override protected MetricRegistry getMetricRegistry() { return REGISTRY; } } 

Then, we add these into the web.xml:

  com.baeldung.metrics.servlet.MyInstrumentedFilterContextListener    instrumentFilter  com.codahale.metrics.servlet.InstrumentedFilter    instrumentFilter /* 

Now the InstrumentedFilter can work. If we want to access its metrics data, we can do it through its MetricRegistryREGISTRY.

7. Other Modules

Except for the modules we introduced above, Metrics has some other modules for different purposes:

  • metrics-jvm: provides several useful metrics for instrumenting JVM internals
  • metrics-ehcache: provides InstrumentedEhcache, a decorator for Ehcache caches
  • metrics-httpclient: provides classes for instrumenting Apache HttpClient (4.x version)
  • metrics-log4j: provides InstrumentedAppender, a Log4j Appender implementation for log4j 1.x which records the rate of logged events by their logging level
  • metrics-log4j2: is similar to metrics-log4j, just for log4j 2.x
  • metrics-logback: provides InstrumentedAppender, a Logback Appender implementation which records the rate of logged events by their logging level
  • メトリック-JSON:提供HealthCheckModuleMetricsModuleをジャクソンのために

さらに、これらのメインプロジェクトモジュール以外に、他のサードパーティライブラリが他のライブラリやフレームワークとの統合を提供します。

8.結論

アプリケーションのインストルメンテーションは一般的な要件であるため、この記事では、問題の解決に役立つことを期待して、メトリックを紹介しました。

いつものように、この例の完全なソースコードはGitHubで入手できます。