第3章 Quarkus アプリケーションのカスタムメトリクス


Micrometer は、独自のカスタムメトリクスを作成できる API を提供します。モニタリングシステムでサポートされる最も一般的なメータータイプは、ゲージ、カウンター、およびサマリーです。以下のセクションでは、サンプルエンドポイントをビルドし、これらの基本メータータイプを使用してエンドポイントの動作を監視します。

メーターを登録するには、Micrometer エクステンションで設定および維持される MeterRegistry への参照が必要です。MeterRegistry は、以下のようにアプリケーションに注入することができます。

package org.acme.micrometer;

import io.micrometer.core.instrument.MeterRegistry;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path("/")
@Produces("text/plain")
public class ExampleResource {

    private final MeterRegistry registry;

    ExampleResource(MeterRegistry registry) {
        this.registry = registry;
    }
}
Copy to Clipboard Toggle word wrap

Micrometer には規則があります。たとえば、a.name.like.this のように、メーターの作成および名前付けではドットを使用してセグメントを分けなければなりません。続いて Micrometer は、その名前を選択したレジストリーが優先する形式に変換します。Prometheus はアンダースコアを使用するため、以前の名前は Prometheus 形式のメトリクス出力では a_name_like_this と表示されます。

Micrometer は、一意のメトリクス識別子とタグの組み合わせと、特定のメーターインスタンスとの間の内部マッピングを維持します。registercounter、またはその他のメソッドを使用してカウンターやレコードの値をインクレメントしても、識別子とタグのその組み合わせまたはラベルの値が以前に確認されていない限り、メーターの新規インスタンスは作成されません。

ゲージ

ゲージは、車の速度計のように時間の経過と共に増減する値を測定します。ゲージは、キャッシュまたはコレクションの統計をモニタリングする際に便利です。リストのサイズを監視する以下の簡単な例を検討してください。

    LinkedList<Long> list = new LinkedList<>();

    // Update the constructor to create the gauge
    ExampleResource(MeterRegistry registry) {
        this.registry = registry;
        registry.gaugeCollectionSize("example.list.size", Tags.empty(), list);
    }

    @GET
    @Path("gauge/{number}")
    public Long checkListSize(@PathParam("number") long number) {
        if (number == 2 || number % 2 == 0) {
            // add even numbers to the list
            list.add(number);
        } else {
            // remove items from the list for odd numbers
            try {
                number = list.removeFirst();
            } catch (NoSuchElementException nse) {
                number = 0;
            }
        }
        return number;
    }
Copy to Clipboard Toggle word wrap

Prometheus を使用する場合、作成されたゲージの値とリストのサイズは、Prometheus エンドポイントへのアクセスの際に監視されます。ゲージは設定ではなくサンプリングされることを重要な点として留意してください。ゲージと関連付けられる値が測定間でどのように変更された可能性があるかという記録はありません。

Micrometer は、ゲージを作成するための追加のメカニズムを提供します。Micrometer は、デフォルトで監視するオブジェクトへの強力な参照を作成しない点に留意してください。Micrometer はレジストリーに応じて、ガベージコレクションが設定されたオブジェクトを監視するゲージをすべて除外するか、または監視値として (数値以外の) NaN を使用します。

カウントできるものは測定しないでください。ゲージの使用はカウンターよりも難しい場合があります。(値が常にインクリメントするため) 測定中のものがカウントできる場合は、代わりにカウンターを使用してください。

カウンター

カウンターは、増加する値だけを測定するために使用されます。以下の例では、素数かどうかを確認するために数値をテストする回数をカウントします。

    @GET
    @Path("prime/{number}")
    public String checkIfPrime(@PathParam("number") long number) {
        if (number < 1) {
            return "Only natural numbers can be prime numbers.";
        }
        if (number == 1 || number == 2 || number % 2 == 0) {
            return number + " is not prime.";
        }

        if ( testPrimeNumber(number) ) {
            return number + " is prime.";
        } else {
            return number + " is not prime.";
        }
    }

    protected boolean testPrimeNumber(long number) {
        // Count the number of times we test for a prime number
        registry.counter("example.prime.number").increment();
        for (int i = 3; i < Math.floor(Math.sqrt(number)) + 1; i = i + 2) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }
Copy to Clipboard Toggle word wrap

確認された値を示すカウンターにラベルまたはタグを追加したくなるかもしれません。メトリクス名 (testPrimeNumber) とラベル値の一意の組み合わせはそれぞれ、一意の時系列を生成する点に留意してください。無制限のデータセットをラベル値として使用すると、新しい時系列が指数関数的に増加するカーディナリティーの爆発につながる可能性があります。

ただし、情報をもう少し伝えるラベルを追加することは可能です。以下の例では、カウンターを移動して一部のラベルを追加するように調整されました。

    @GET
    @Path("prime/{number}")
    public String checkIfPrime(@PathParam("number") long number) {
        if (number < 1) {
            registry.counter("example.prime.number", "type", "not-natural").increment();
            return "Only natural numbers can be prime numbers.";
        }
        if (number == 1 ) {
            registry.counter("example.prime.number", "type", "one").increment();
            return number + " is not prime.";
        }
        if (number == 2 || number % 2 == 0) {
            registry.counter("example.prime.number", "type", "even").increment();
            return number + " is not prime.";
        }

        if ( testPrimeNumber(number) ) {
            registry.counter("example.prime.number", "type", "prime").increment();
            return number + " is prime.";
        } else {
            registry.counter("example.prime.number", "type", "not-prime").increment();
            return number + " is not prime.";
        }
    }

    protected boolean testPrimeNumber(long number) {
        for (int i = 3; i < Math.floor(Math.sqrt(number)) + 1; i = i + 2) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }
Copy to Clipboard Toggle word wrap

このカウンターによって生成されたデータを確認すると、負数、数字の 1、または偶数などを確認した頻度がわかります。以下のシーケンスを試し、プレーンテキストの出力で example_prime_number_total を探します。Micrometer が Prometheus 命名規則を _total (最初に指定したカウンター名) に適用すると、example.prime.number 接尾辞が追加される点に留意してください。

# If you did not leave quarkus running in dev mode, start it again:
./mvnw compile quarkus:dev

curl http://localhost:8080/example/prime/-1
curl http://localhost:8080/example/prime/0
curl http://localhost:8080/example/prime/1
curl http://localhost:8080/example/prime/2
curl http://localhost:8080/example/prime/3
curl http://localhost:8080/example/prime/15
curl http://localhost:8080/q/metrics
Copy to Clipboard Toggle word wrap

時間の計測またはサマライズが可能な場合は、カウントしないでください。カウンターはカウントしたものだけを記録します。これは、カウントしたものだけで十分な場合が多いからです。ただし、値が変更される方法を理解する必要がある場合は、タイマー (測定の基準単位が時間の場合)、またはディストリビューションサマリーの方が適している場合もあります。

サマリーとタイマー

Micrometer におけるタイマーとディストリビューションサマリーは非常に似ています。いずれの場合も、監視値を記録することができます。これは、他の記録値と共に集計され、合計として保存されます。また、Micrometer は記録された測定回数を示すカウンターをインクリメントし、指定された時間間隔内で監視された最大値を追跡します。

ディストリビューションサマリーは、監視値を記録するために record メソッドを呼び出して設定されますが、タイマーは、時間および測定期間に固有の追加機能を提供します。たとえば、タイマーを使用し、Supplier 関数の呼び出しをラップする record メソッドのいずれかを使用して素数を数える際にかかる時間を測定できます。

    protected boolean testPrimeNumber(long number) {
        Timer timer = registry.timer("example.prime.number.test");
        return timer.record(() -> {
            for (int i = 3; i < Math.floor(Math.sqrt(number)) + 1; i = i + 2) {
                if (number % i == 0) {
                    return false;
                }
            }
            return true;
        });
    }
Copy to Clipboard Toggle word wrap

Micrometer は、このタイマーのメトリクスを生成する際に Prometheus の規則を適用します。Prometheus は時間を秒単位で計測します。Micrometer は測定期間を秒単位に変換し、規則ごとにメトリクス名に単位を含めます。prime エンドポイントに数回移動した後、プレーンテキストの出力で、example_prime_number_test_seconds_countexample_prime_number_test_seconds_sum、および example_prime_number_test_seconds_max の 3 つのエントリーを検索します。

# If you did not leave quarkus running in dev mode, start it again:
./mvnw compile quarkus:dev

curl http://localhost:8080/example/prime/256
curl http://localhost:8080/q/metrics
curl http://localhost:8080/example/prime/7919
curl http://localhost:8080/q/metrics
Copy to Clipboard Toggle word wrap

タイマーとディストリビューションサマリーはいずれも、ヒストグラムデータ、事前計算されたパーセンタイル、またはサービスレベル目標 (SLO) の境界など、追加の統計を生成するように設定することができます。カウント、合計、およびヒストグラムのデータは、ディメンション全体で (または一連のインスタンスをまたいで) 再集計できますが、事前計算されたパーセンタイル値は再集計できない点に留意してください。

Red Hat logoGithubredditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。 最新の更新を見る.

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

Theme

© 2026 Red Hat
トップに戻る