Dropwizardメトリックの紹介

Dropwizardメトリックスの紹介

1. 前書き

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

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

2. モジュールmetrics-core

2.1. Mavenの依存関係

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


    io.dropwizard.metrics
    metrics-core
    3.1.2

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

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」を取得しています。 )s。

上記のメトリック名として「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. メトリックの概念

メトリックコアモジュールは、いくつかの一般的に使用されるメトリックタイプを提供します:MeterGaugeCounterHistogramTimer、およびReporterを出力しますメトリックの値.

3.1. Meter

Meterは、イベントの発生回数と発生率を測定します。

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()メソッドはイベント発生数を返し、mark()メソッドはイベント発生数に1またはnを追加します。 Meterオブジェクトは、Meterの存続期間全体、最近1分間、最近5分間、および最近四半期の平均レートをそれぞれ表す4つのレートを提供します。

3.2. Gauge

Gaugeは、特定の値を返すために使用されるインターフェイスです。 メトリックコアモジュールは、RatioGaugeCachedGaugeDerivativeGauge、およびJmxAttributeGaugeのいくつかの実装を提供します。

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, Integer> {

    @Override
    protected Integer transform(List value) {
        return value.size();
    }

    // standard constructors
}

このGaugeは、その値をActiveUsersGaugeから導出するため、基本リストのサイズからの値であると予想されます。

Gauge> activeUsersGauge = new ActiveUsersGauge(15, TimeUnit.MINUTES);
Gauge activeUserCountGauge = new ActiveUserCountGauge(activeUsersGauge);

assertThat(activeUserCountGauge.getValue(), equalTo(1));

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

3.3. Counter

Counterは、増分と減分を記録するために使用されます。

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. Histogram

Histogramは、Long値のストリームを追跡するために使用され、max, min, mean, median, standard deviation, 75th percentileなどの統計的特性を分析します。

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は、リザーバーサンプリングを使用してデータをサンプリングします。Histogramオブジェクトをインスタンス化するときは、そのリザーバーを明示的に設定する必要があります。

Reservoirはインターフェースであり、metrics-coreはそれらの4つの実装を提供します:ExponentiallyDecayingReservoirUniformReservoirSlidingTimeWindowReservoirSlidingWindowReservoir.

上記のセクションでは、コンストラクター.を使用する以外に、MetricRegistry,によってメトリックを作成することもできると述べました。metricRegistry.histogram()を使用すると、HistogramインスタンスがExponentiallyDecayingReservoirの実装。

3.5. Timer

Timerは、Contextオブジェクトによって表される複数のタイミング期間を追跡するために使用され、統計データも提供します。

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

測定値を出力する必要がある場合は、Reporterを使用できます。 これはインターフェースであり、metrics-coreモジュールは、ConsoleReporterCsvReporterSlf4jReporterJmxReporterなどのいくつかの実装を提供します。

ここでは、例としてConsoleReporterを使用します。

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();

これが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. モジュールmetrics-healthchecks

メトリックスには、ヘルスチェックを処理するための拡張メトリックス-ヘルスチェックモジュールがあります。

4.1. Mavenの依存関係

metrics-healthchecksモジュールを使用するには、この依存関係をpom.xmlファイルに追加する必要があります。


    io.dropwizard.metrics
    metrics-healthchecks
    3.1.2

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

4.2. 使用法

まず、特定のヘルスチェック操作を担当するいくつかのクラスが必要であり、これらのクラスはHealthCheckを実装する必要があります。

たとえば、DatabaseHealthCheckUserCenterHealthCheckを使用します。

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();
    }
}

次に、HealthCheckRegistryMetricRegistryと同じ)が必要で、DatabaseHealthCheckUserCenterHealthCheckを登録します。

HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();
healthCheckRegistry.register("db", new DatabaseHealthCheck());
healthCheckRegistry.register("uc", new UserCenterHealthCheck());

assertThat(healthCheckRegistry.getNames().size(), equalTo(2));

HealthCheckの登録を解除することもできます。

healthCheckRegistry.unregister("uc");

assertThat(healthCheckRegistry.getNames().size(), equalTo(1));

すべてのHealthCheckインスタンスを実行できます。

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

最後に、特定のHealthCheckインスタンスを実行できます。

healthCheckRegistry.runHealthCheck("db");

5. モジュールmetrics-servlets

メトリックは、HTTPリクエストを介してメトリック関連のデータにアクセスできる便利なサーブレットをいくつか提供します。

5.1. Mavenの依存関係

メトリックサーボモジュールを使用するには、この依存関係をpom.xmlファイルに追加する必要があります。


    io.dropwizard.metrics
    metrics-servlets
    3.1.2

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

5.2. HealthCheckServlet使用法

HealthCheckServletは、ヘルスチェックの結果を提供します。 まず、HealthCheckRegistryを公開するServletContextListenerを作成する必要があります。

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;
    }
}

次に、このリスナーとHealthCheckServletの両方をweb.xmlファイルに追加します。


    com.example.metrics.servlets.MyHealthCheckServletContextListener


    healthCheck
    com.codahale.metrics.servlets.HealthCheckServlet


    healthCheck
    /healthcheck

これで、Webアプリケーションを起動し、「http:// localhost:8080 / healthcheck」にGETリクエストを送信して、ヘルスチェック結果を取得できます。 その応答は次のようになります。

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

5.3. ThreadDumpServlet使用法

ThreadDumpServletは、JVM内のすべてのライブスレッド、それらの状態、それらのスタックトレース、およびそれらが待機している可能性のあるロックの状態に関する情報を提供します。 これを使用する場合は、これらをweb.xmlファイルに追加するだけです。


    threadDump
    com.codahale.metrics.servlets.ThreadDumpServlet


    threadDump
    /threaddump

スレッドダンプデータは、「http:// localhost:8080 / threaddump」で入手できます。

5.4. PingServlet使用法

PingServletを使用して、アプリケーションが実行されているかどうかをテストできます。 これらをweb.xmlファイルに追加します。


    ping
    com.codahale.metrics.servlets.PingServlet


    ping
    /ping

次に、GET要求を「http:// localhost:8080 / ping」に送信します。 応答のステータスコードは200で、その内容は「ポン」です。

5.5. MetricsServlet使用法

MetricsServletはメトリックデータを提供します。 まず、MetricRegistryを公開するServletContextListenerを作成する必要があります。

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;
    }
}

このリスナーとMetricsServletの両方をweb.xmlに追加する必要があります。


    com.codahale.metrics.servlets.MyMetricsServletContextListener


    metrics
    com.codahale.metrics.servlets.MetricsServlet


    metrics
    /metrics

これは、「http:// localhost:8080 / metrics」のWebアプリケーションで公開されます。 その応答には、さまざまなメトリックデータが含まれている必要があります。

{
  "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使用法

AdminServletは、HealthCheckServletThreadDumpServletMetricsServlet、およびPingServletを集約します。

これらをweb.xmlに追加しましょう:


    admin
    com.codahale.metrics.servlets.AdminServlet


    admin
    /admin/*

これで、「http:// localhost:8080 / admin」でアクセスできます。 これらの4つのサーブレットのそれぞれに1つずつ、4つのリンクを含むページを取得します。

ヘルスチェックを行い、メトリックデータにアクセスする場合、これらの2つのリスナーが引き続き必要であることに注意してください。

6. モジュールmetrics-servlet

metrics-servletモジュールは、いくつかのメトリックを持つFilterを提供します。ステータスコードのメーター、アクティブな要求の数のカウンター、および要求期間のタイマーです。

6.1. Mavenの依存関係

このモジュールを使用するには、最初に依存関係をpom.xmlに追加しましょう。


    io.dropwizard.metrics
    metrics-servlet
    3.1.2

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

6.2. 使用法

これを使用するには、MetricRegistryInstrumentedFilterに公開するServletContextListenerを作成する必要があります。

public class MyInstrumentedFilterContextListener
  extends InstrumentedFilterContextListener {

    public static MetricRegistry REGISTRY = new MetricRegistry();

    @Override
    protected MetricRegistry getMetricRegistry() {
        return REGISTRY;
    }
}

次に、これらをweb.xmlに追加します。


     
         com.example.metrics.servlet.MyInstrumentedFilterContextListener
     



    instrumentFilter
    
        com.codahale.metrics.servlet.InstrumentedFilter
    


    instrumentFilter
    /*

これで、InstrumentedFilterが機能します。 メトリックデータにアクセスする場合は、MetricRegistryREGISTRYを介してアクセスできます。

7. その他のモジュール

上記で紹介したモジュールを除き、Metricsにはさまざまな目的のための他のモジュールがいくつかあります。

  • metrics-jvm:JVM内部をインストルメント化するためのいくつかの有用なメトリックを提供します

  • metrics-ehcache:EhcacheキャッシュのデコレータであるInstrumentedEhcacheを提供します

  • metrics-httpclient:Apache HttpClient(4.xバージョン)をインストルメント化するためのクラスを提供します

  • metrics-log4j:ログレベルごとにログイベントの割合を記録するlog4j 1.xのLog4jAppender実装であるInstrumentedAppenderを提供します

  • metrics-log4j2:log4j 2.xの場合のみ、metric-log4jに似ています

  • metrics-logback:ログレベルごとにログイベントの割合を記録するログバックAppender実装であるInstrumentedAppenderを提供します

  • metrics-json:ジャクソンにHealthCheckModuleMetricsModuleを提供します

さらに、これらのメインプロジェクトモジュール以外に、他のいくつかのthird party librariesが他のライブラリやフレームワークとの統合を提供します。

8. 結論

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

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