CLOVER🍀

That was when it all began.

Infinispan Server 14.0でメトリクスの収集方法がMicrometerに移行されたので、試してみた

これは、なにをしたくて書いたもの?

Infinispan 14.0.0.Finalで、メトリクスの生成にMicrometerを使うようになったみたいです。

Integration with Micrometer to produce Prometheus and OpenMetrics metrics

Infinispan 14.0.0.Final

こちらを簡単に確認したいと思います。

Infinispan Serverでのメトリクス収集方法の変遷

Infinispan(Infinispan Server)でのメトリクスの収集方法は、過去にいろいろ変わってきました。

自分も過去に少し試しています。

Infinispan 9.4.1.Finalで追加された、Prometheus Exporterを試す - CLOVER🍀

Infinispan Server 13.0とHot Rod Clientでメトリクスを取得する - CLOVER🍀

Infinispan Serverのメトリクスに関するドキュメントは、こちら。

Guide to Infinispan Server / Enabling and configuring Infinispan statistics and JMX monitoring

JMX MBeanは以前からずっとあります。

変わっているのは、HTTPでのメトリクス取得方法ですね。ちょっと見返してみたのですが、こんな感じで変わってきたようです。

Infinispan 9.2.0.FinalでJolokia。

ISPN-7599 Jolokia support by slaskawi · Pull Request #5267 · infinispan/infinispan · GitHub

Infinispan 9.2.0.Final

Infinispan 9.4.1.FinalでPrometheus Exporter。

ISPN-9558 Export Data Grid stats to Prometheus by vblagoje · Pull Request #6290 · infinispan/infinispan · GitHub

Infinispan 9.4.1.Final and Infinispan Spring Boot Starter 2.1.0.Final are out!

Infinispan 10.0.0.FinalでSmallRye Metrics。

ISPN-10244 Smallrye metrics: gauges by anistor · Pull Request #7407 · infinispan/infinispan · GitHub

[ISPN-10244] Observability: use smallrye metrics - Red Hat Issue Tracker

Infinispan 10.0 “Chupacabra”

そして、Infinispan 14.0.0.FinalでMicrometer。

ISPN-12991 Replace Smallrye metrics with Micrometer by fax4ever · Pull Request #9933 · infinispan/infinispan · GitHub

[ISPN-12991] Replace Smallrye metrics with Micrometer - Red Hat Issue Tracker

Infinispan 14.0.0.Final

この時にSmallRye Metricsを使ったバージョンで試していたので、Micrometerに変わるまで短かったような感覚になりましたが、
単に触っていなかっただけみたいです…。

Infinispan Server 13.0とHot Rod Clientでメトリクスを取得する - CLOVER🍀

Hot Rod ClientはずっとJMX MBeanですね。

Guide to Infinispan Server / Enabling and configuring Infinispan statistics and JMX monitoring / Enabling Hot Rod client statistics

Infinispan Serverのメトリクスに関するドキュメントを確認する

Infinispan Serverに関するメトリクスについて、もう1度確認してみます。

Guide to Infinispan Server / Enabling and configuring Infinispan statistics and JMX monitoring

どちらも、明示的に有効化(statisticstrueにする)必要があります。

ちなみに、Embeddedの方も含めるとこちらにまるっと同じ内容が書かれているようです。

Configuring Infinispan caches / Enabling and configuring Infinispan statistics and JMX monitoring

Micrometerが使われているということでしたが、実装としてはMicrometer Prometeusが利用されているようです。

Micrometer Prometheus

バージョンとしては、1.9.2が使われているようです。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/configuration/pom.xml#L202

CacheManagerおよびCacheに関するXML Schema定義はこちら。

urn:infinispan:config:14.0

メトリクスに関する記述を抜粋しておきましょう。

CacheManagerレベル。

Cacheレベル。

今回、SmallRye MetricsからMicrometerに移行されたので、メトリクスの名称が変わったりするのかなと思ったのですが、basevendorといった
スコープは引き続き使われるようです。

Infinispan metrics are provided at the vendor scope. Metrics related to the JVM are provided in the base scope.

Guide to Infinispan Server / Enabling and configuring Infinispan statistics and JMX monitoring / Configuring Infinispan metrics

メトリクスの収集を有効にすると、HTTPで/metricsエンドポイントでメトリクスを取得できるようになります。

メトリクスのフォーマットは以下の2つです。

  • Prometheus Format
  • OpenMetrics Format

Exposition formats | Prometheus

SmallRye Metricsを使っていた頃はJSON Formatもありましたが、こちらは廃止になったようです。

Infinispan no longer provides metrics in MicroProfile JSON format.

フォーマットは、Micrometer側で対応しているみたいですね。このあたりは、あとで少し追ってみます。

OpenMetrics scrape support by shakuzen · Pull Request #2486 · micrometer-metrics/micrometer · GitHub

取得対象のメトリクスは、CacheManagerCacheについては主にJMX MBeanの情報を参照することになるのですが、完全に同じでは
ありません。

JMX Components

このあたりもあとで少し書くとして、Infinispan ServerやHot Rod Clientからメトリクスを取得するように試してみましょう。
最終的には、Prometheusで収集するようにしてみます。

流れとしては、SmallRye Metricsの時に書いたエントリーの焼き直しなのですが。最後にソースコードを追う部分以外は、そんなに変わりませんね。

環境

今回の環境は、こちら。

$ java --version
openjdk 17.0.5 2022-10-18
OpenJDK Runtime Environment (build 17.0.5+8-Ubuntu-2ubuntu120.04)
OpenJDK 64-Bit Server VM (build 17.0.5+8-Ubuntu-2ubuntu120.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 17.0.5, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-132-generic", arch: "amd64", family: "unix"

Infinispan Serverは、172.18.0.2〜172.18.0.4の3つのノードで動作し、クラスターを構成しているものとします。

$ java --version
openjdk 17.0.5 2022-10-18
OpenJDK Runtime Environment Temurin-17.0.5+8 (build 17.0.5+8)
OpenJDK 64-Bit Server VM Temurin-17.0.5+8 (build 17.0.5+8, mixed mode, sharing)


$ bin/server.sh --version

Infinispan Server 14.0.2.Final (Flying Saucer)
Copyright (C) Red Hat Inc. and/or its affiliates and other contributors
License Apache License, v. 2.0. http://www.apache.org/licenses/LICENSE-2.0

起動コマンドはこちら。

$ bin/server.sh \
    -b 0.0.0.0 \
    -Djgroups.tcp.address=$(hostname -i)

Prometheusは、172.18.0.5で動作しているものとします。

$ ./prometheus --version
prometheus, version 2.40.3 (branch: HEAD, revision: 84e95d8cbc51b89f1a69b25dd239cae2a44cb6c1)
  build user:       root@72aff466572b
  build date:       20221124-09:08:44
  go version:       go1.19.3
  platform:         linux/amd64

準備

テストコードで使う、Maven依存関係など。

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.infinispan</groupId>
            <artifactId>infinispan-client-hotrod</artifactId>
            <version>14.0.2.Final</version>
        </dependency>

        <dependency>
            <groupId>org.infinispan</groupId>
            <artifactId>infinispan-core</artifactId>
            <version>14.0.2.Final</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.9.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>3.23.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
        </plugins>
    </build>

各Infinispan Serverには、それぞれ管理用ユーザー、アプリケーションユーザーを作成しておきます。

$ bin/cli.sh user create -g admin -p password ispn-admin
$ bin/cli.sh user create -g application -p password ispn-user

また、メトリクスを取得するためにInfinispan Serverにアクセスする際には、REST Connector経由になります。この時に認証の設定をどうするか
決めておく必要がありますが、今回は認証設定を行うことにします。

デフォルトではこのようになっているendpointsの設定を

      <endpoints socket-binding="default" security-realm="default" />

以下のように変更。

      <endpoints socket-binding="default" security-realm="default">
         <endpoint>
            <hotrod-connector>
               <authentication>
                  <sasl mechanisms="SCRAM-SHA-512 SCRAM-SHA-384 SCRAM-SHA-256
                                  SCRAM-SHA-1 DIGEST-SHA-512 DIGEST-SHA-384
                                  DIGEST-SHA-256 DIGEST-SHA DIGEST-MD5 PLAIN"
                        server-name="infinispan"
                        qop="auth"/>
               </authentication>
            </hotrod-connector>
            <rest-connector>
               <authentication mechanisms="DIGEST BASIC"/>
            </rest-connector>
         </endpoint>
      </endpoints>

REST Connector自体はデフォルトで有効で、Digest認証が使えるようになっているのですが、今回はPrometheusからアクセスするので
Basic認証も追加する必要があります。

このように設定すると、REST Connector、Hot Rod Connectorともに設定を明示的に行う必要があります。

Infinispan Serverからメトリクスを取得してみる

まずは、起動しただけのInfinispan Serverからメトリクスを取得してみましょう。

server/conf/infinispan.xmlはデフォルトで以下の状態になっているため、このままでメトリクスを取得できます。

   <cache-container name="default" statistics="true">

Prometheus Formatで取得。

## Digest認証
$ curl --digest -u ispn-user:password 172.18.0.2:11222/metrics


## Basic認証
$ curl -u ispn-user:password 172.18.0.2:11222/metrics

アクセスは、アプリケーション用のユーザーで大丈夫です。

OpenMetrics Formatで取得。

## Digest認証
$ curl --digest -u ispn-user:password -H 'Accept: application/openmetrics-text' 172.18.0.2:11222/metrics


## Basic認証
$ curl -u ispn-user:password -H 'Accept: application/openmetrics-text' 172.18.0.2:11222/metrics

特に操作していない状態でも、このくらいのメトリクスを取得できます。

## Prometheus Format
$ curl -s -u ispn-user:password 172.18.0.2:11222/metrics | grep -v '#' | wc -l
172


## OpenMetrics Format
$ curl -s -u ispn-user:password -H 'Accept: application/openmetrics-text' 172.18.0.2:11222/metrics | grep -v '#' | wc -l
172

取得したメトリクスの例。

$ curl -s -u ispn-user:password 172.18.0.2:11222/metrics | grep -v '#' | head -n 30
base_classloader_loadedClasses_total 11384.0
base_thread_totalStarted 56.0
vendor_jgroups_cluster_fd_sock2_get_actual_bind_port{node="infinispan-server-18034",} 57800.0
base_memory_committedNonHeap_bytes 8.0019456E7
vendor_jgroups_cluster_tcp_get_num_msgs_received{node="infinispan-server-18034",} 197.0
vendor_jgroups_cluster_tcp_get_thread_pool_size{node="infinispan-server-18034",} 4.0
vendor_cache_manager_default_cache_container_stats_evictions{node="infinispan-server-18034",} 0.0
vendor_jgroups_cluster_ufc_get_number_of_credit_responses_sent{node="infinispan-server-18034",} 0.0
vendor_jgroups_cluster_nakack2_get_xmit_table_num_moves{node="infinispan-server-18034",} 0.0
vendor_jgroups_cluster_tcp_get_num_ucast_bytes_received{node="infinispan-server-18034",} 0.0
vendor_jgroups_cluster_unicast3_get_num_send_connections{node="infinispan-server-18034",} 2.0
vendor_cache_manager_default_cache_container_stats_required_minimum_number_of_nodes{node="infinispan-server-18034",} -1.0
vendor_cache_manager_default_server_single_port_11222_transport_pending_tasks{node="infinispan-server-18034",} 0.0
vendor_memoryPool_CodeHeap__non_profiled_nmethods__usage_max_bytes 2761344.0
vendor_jgroups_cluster_gms_get_view_handler_size{node="infinispan-server-18034",} 0.0
vendor_cache_manager_default_cluster_size{node="infinispan-server-18034",} 3.0
vendor_memoryPool_CodeHeap__profiled_nmethods__usage_max_bytes 1.1169152E7
vendor_cache_manager_default_cache_container_health_number_of_nodes{node="infinispan-server-18034",} 3.0
vendor_cache_manager_default_cache_container_stats_remove_hits{node="infinispan-server-18034",} 0.0
vendor_jgroups_cluster_stable_get_stability_received{node="infinispan-server-18034",} 59.0
vendor_jgroups_cluster_unicast3_get_num_xmits{node="infinispan-server-18034",} 0.0
vendor_jgroups_cluster_frag4_get_number_of_received_fragments{node="infinispan-server-18034",} 0.0
base_cpu_systemLoadAverage 0.89
vendor_jgroups_cluster_unicast3_get_xmit_table_undelivered_messages{node="infinispan-server-18034",} 0.0
vendor_cache_manager_default_local_container_stats_memory_max{node="infinispan-server-18034",} 5.36870912E8
vendor_cache_manager_default_cache_container_stats_time_since_reset{node="infinispan-server-18034",} 399.0
vendor_jgroups_cluster_tcp_get_num_ucast_msgs_received{node="infinispan-server-18034",} 0.0
base_cpu_processCpuLoad 6.451612903225806E-4
vendor_jgroups_cluster_unicast3_get_num_connections{node="infinispan-server-18034",} 4.0
vendor_cache_manager_default_local_container_stats_time_since_reset{node="infinispan-server-18034",} 399.0

〜省略〜

以降は、Prometheus FormatでBasic認証を使ってアクセスすることにします。

スコープはbasevendorの2種類があるということでしたが、この時点では以下のような分布になっています。

$ curl -s -u ispn-user:password 172.18.0.2:11222/metrics | grep -v '#' | perl -wp -e 's!^([^_]+).+!$1!' | sort | uniq -c
     24 base
    148 vendor

少し挙動を確認してみましょう。statisticsfalseにしてInfinispan Serverを再起動。

   <cache-container name="default" statistics="false">

すると、CacheManagerに関するメトリクスが取得できなくなります。

$ curl -s -u ispn-user:password 172.18.0.2:11222/metrics | grep -v '#' | wc -l
127

メトリクス自体が全く取得できなくなるわけではなさそうですね。

では、CacheManagerに関するメトリクスは?というと名前にcache_managercache_containerが入っているものが該当しそうです。

$ curl -s -u ispn-user:password 172.18.0.2:11222/metrics | grep -v '#' | grep cache_manager | grep cache_container
vendor_cache_manager_default_cache_container_stats_number_of_entries{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_health_number_of_nodes{node="infinispan-server-33644",} 3.0
vendor_cache_manager_default_cache_container_health_number_of_cpus{node="infinispan-server-33644",} 8.0
vendor_cache_manager_default_cache_container_stats_average_write_time{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_misses{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_average_read_time{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_off_heap_memory_used{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_hits{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_average_remove_time{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_average_write_time_nanos{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_health_total_memory_kb{node="infinispan-server-33644",} 67584.0
vendor_cache_manager_default_cache_container_stats_remove_misses{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_average_remove_time_nanos{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_time_since_reset{node="infinispan-server-33644",} 20.0
vendor_cache_manager_default_cache_container_stats_current_number_of_entries_in_memory{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_health_free_memory_kb{node="infinispan-server-33644",} 22656.0
vendor_cache_manager_default_cache_container_stats_required_minimum_number_of_nodes{node="infinispan-server-33644",} -1.0
vendor_cache_manager_default_cache_container_stats_remove_hits{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_time_since_start{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_data_memory_used{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_hit_ratio{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_stores{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_evictions{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_read_write_ratio{node="infinispan-server-33644",} 0.0
vendor_cache_manager_default_cache_container_stats_average_read_time_nanos{node="infinispan-server-33644",} 0.0

デフォルトでは取得できるメトリクスはgauseのみです。
※一部、FunctionCounterも混じっているようですが

$ curl -s -u ispn-user:password 172.18.0.2:11222/metrics | grep gauge| head -n 10
# TYPE base_thread_totalStarted gauge
# TYPE vendor_jgroups_cluster_unicast3_get_num_send_connections gauge
# TYPE base_memory_committedNonHeap_bytes gauge
# TYPE vendor_jgroups_cluster_nakack2_get_xmit_table_num_compactions gauge
# TYPE vendor_jgroups_cluster_nakack2_get_non_member_messages gauge
# TYPE vendor_cache_manager_default_cache_container_stats_number_of_entries gauge
# TYPE vendor_cache_manager_default_cache_container_health_number_of_nodes gauge
# TYPE vendor_jgroups_cluster_unicast3_get_xmit_table_num_compactions gauge
# TYPE vendor_jgroups_cluster_red_get_total_messages gauge
# TYPE vendor_jgroups_cluster_mfc_get_number_of_credit_requests_sent gauge

〜省略〜

histogramを有効にする場合は、以下のように設定します。

   <cache-container name="default" statistics="true">
      <metrics gauges="true"
               histograms="true" />

起動しただけだと、histogramによるメトリクスは取得できないのですが…。

Cacheを作成、利用してからメトリクスを取得する

次に、Cacheを作成してからメトリクスを取得してみます。

こちらは、テストコードで行います。まずは以下のような雛形を用意。

src/test/java/org/littlewings/infinispan/remote/metrics/MetricsTest.java

package org.littlewings.infinispan.remote.metrics;

import java.util.stream.IntStream;

import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.RemoteCacheManagerAdmin;
import org.infinispan.client.hotrod.ServerStatistics;
import org.infinispan.client.hotrod.configuration.Configuration;
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
import org.infinispan.client.hotrod.jmx.RemoteCacheClientStatisticsMXBean;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class MetricsTest {
    static String createUri(String userName, String password) {
        return String.format("hotrod://%s:%s@172.18.0.2:11222,172.18.0.3:11222,172.18.0.4:11222", userName, password);
    }

    @BeforeAll
    static void setUpAll() {
        String uri = createUri("ispn-admin", "password");

        try (RemoteCacheManager manager = new RemoteCacheManager(uri)) {
            RemoteCacheManagerAdmin admin = manager.administration();

            org.infinispan.configuration.cache.Configuration distCacheConfiguration =
                    new org.infinispan.configuration.cache.ConfigurationBuilder()
                            .clustering()
                            .cacheMode(org.infinispan.configuration.cache.CacheMode.DIST_SYNC)
                            .encoding().key().mediaType("application/x-protostream")
                            .encoding().value().mediaType("application/x-protostream")
                            .statistics().enable()
                            .build();

            admin.getOrCreateCache("distCache", distCacheConfiguration);

            org.infinispan.configuration.cache.Configuration replCacheConfiguration =
                    new org.infinispan.configuration.cache.ConfigurationBuilder()
                            .clustering()
                            .cacheMode(org.infinispan.configuration.cache.CacheMode.REPL_SYNC)
                            .encoding().key().mediaType("application/x-protostream")
                            .encoding().value().mediaType("application/x-protostream")
                            .statistics().enable()
                            .build();

            admin.getOrCreateCache("replCache", replCacheConfiguration);
        }
    }

    // ここに、テストを書く!!
}

Cacheは、テスト実行時に作成することにします。今回はDistributed CacheとReplicated Cacheの2つを作成。

デフォルトではCacheのメトリクスの記録は無効になっているので、明示的に有効化する必要があります。

これでInfinispan Server側に作成されるCacheの定義は、以下のようになります。

server/data/caches.xml

<?xml version="1.0"?>
<infinispan xmlns="urn:infinispan:config:14.0">
    <cache-container>
        <caches>
            <replicated-cache name="replCache" mode="SYNC" remote-timeout="17500" statistics="true">
                <encoding>
                    <key media-type="application/x-protostream"/>
                    <value media-type="application/x-protostream"/>
                </encoding>
                <locking concurrency-level="1000" acquire-timeout="15000" striping="false"/>
                <state-transfer timeout="60000"/>
            </replicated-cache>
            <distributed-cache name="distCache" mode="SYNC" remote-timeout="17500" statistics="true">
                <encoding>
                    <key media-type="application/x-protostream"/>
                    <value media-type="application/x-protostream"/>
                </encoding>
                <locking concurrency-level="1000" acquire-timeout="15000" striping="false"/>
                <state-transfer timeout="60000"/>
            </distributed-cache>
        </caches>
    </cache-container>
</infinispan>

これらのCacheを使う、テストコード。

    @Test
    public void distributedCache() {
        String uri = createUri("ispn-user", "password");

        try (RemoteCacheManager manager = new RemoteCacheManager(uri)) {
            RemoteCache<String, String> cache = manager.getCache("distCache");

            IntStream
                    .rangeClosed(1, 100)
                    .forEach(i -> cache.put("key" + i, "value" + i));

            IntStream
                    .rangeClosed(1, 50)
                    .forEach(i -> assertThat(cache.get("key" + i)).isNotNull());

            IntStream
                    .rangeClosed(101, 125)
                    .forEach(i -> assertThat(cache.get("key" + i)).isNull());
        }
    }

    @Test
    public void replicatedCache() {
        String uri = createUri("ispn-user", "password");

        try (RemoteCacheManager manager = new RemoteCacheManager(uri)) {
            RemoteCache<String, String> cache = manager.getCache("replCache");

            IntStream
                    .rangeClosed(1, 100)
                    .forEach(i -> cache.put("key" + i, "value" + i));

            IntStream
                    .rangeClosed(1, 50)
                    .forEach(i -> assertThat(cache.get("key" + i)).isNotNull());

            IntStream
                    .rangeClosed(101, 125)
                    .forEach(i -> assertThat(cache.get("key" + i)).isNull());
        }
    }

これらのテストを実行した後に、メトリクスを取得してみます。

$ curl -s -u ispn-user:password 172.18.0.2:11222/metrics | grep -v '#' | wc -l
346

一気に倍くらいになりました。

vendorスコープのものが増えていますね。

$ curl -s -u ispn-user:password 172.18.0.2:11222/metrics | grep -v '#' | perl
-wp -e 's!^([^_]+).+!$1!' | sort | uniq -c
     24 base
    322 vendor

cache_managerで絞り込んで、ソートしてみます。

$ curl -s -u ispn-user:password 172.18.0.2:11222/metrics | grep -v '#' | grep cache_manager | sort
vendor_cache_manager_default_cache_container_health_free_memory_kb{node="infinispan-server-63198",} 13067.0
vendor_cache_manager_default_cache_container_health_number_of_cpus{node="infinispan-server-63198",} 8.0
vendor_cache_manager_default_cache_container_health_number_of_nodes{node="infinispan-server-63198",} 3.0
vendor_cache_manager_default_cache_container_health_total_memory_kb{node="infinispan-server-63198",} 67584.0
vendor_cache_manager_default_cache_container_stats_average_read_time_nanos{node="infinispan-server-63198",} 55291.0
vendor_cache_manager_default_cache_container_stats_average_read_time{node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_container_stats_average_remove_time_nanos{node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_container_stats_average_remove_time{node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_container_stats_average_write_time_nanos{node="infinispan-server-63198",} 1567124.0
vendor_cache_manager_default_cache_container_stats_average_write_time{node="infinispan-server-63198",} 1.0

〜省略〜

vendor_cache_manager_default_cache_distCache_cluster_cache_stats_activations{cache="distCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_approximate_entries_in_memory{cache="distCache",node="infinispan-server-63198",} 200.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_approximate_entries_unique{cache="distCache",node="infinispan-server-63198",} 100.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_approximate_entries{cache="distCache",node="infinispan-server-63198",} 200.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_read_time_nanos{cache="distCache",node="infinispan-server-63198",} 68779.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_read_time{cache="distCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_remove_time_nanos{cache="distCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_remove_time{cache="distCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_write_time_nanos{cache="distCache",node="infinispan-server-63198",} 1756830.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_write_time{cache="distCache",node="infinispan-server-63198",} 1.0
〜省略〜

vendor_cache_manager_default_cache_replCache_cluster_cache_stats_activations{cache="replCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_approximate_entries_in_memory{cache="replCache",node="infinispan-server-63198",} 300.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_approximate_entries_unique{cache="replCache",node="infinispan-server-63198",} 100.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_approximate_entries{cache="replCache",node="infinispan-server-63198",} 300.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_read_time_nanos{cache="replCache",node="infinispan-server-63198",} 50003.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_read_time{cache="replCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_remove_time_nanos{cache="replCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_remove_time{cache="replCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_write_time_nanos{cache="replCache",node="infinispan-server-63198",} 1553920.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_write_time{cache="replCache",node="infinispan-server-63198",} 1.0

〜省略〜

vendor_cache_manager_default_cluster_container_stats_memory_available{node="infinispan-server-63198",} 3.2327152E7
vendor_cache_manager_default_cluster_container_stats_memory_max{node="infinispan-server-63198",} 1.073741824E9
vendor_cache_manager_default_cluster_container_stats_memory_total{node="infinispan-server-63198",} 1.38412032E8
vendor_cache_manager_default_cluster_container_stats_memory_used{node="infinispan-server-63198",} 1.0608488E8
vendor_cache_manager_default_cluster_container_stats_time_since_reset{node="infinispan-server-63198",} 41190.0
vendor_cache_manager_default_cluster_size{node="infinispan-server-63198",} 3.0
vendor_cache_manager_default_local_container_stats_memory_available{node="infinispan-server-63198",} 1.3747984E7
vendor_cache_manager_default_local_container_stats_memory_max{node="infinispan-server-63198",} 5.36870912E8
vendor_cache_manager_default_local_container_stats_memory_total{node="infinispan-server-63198",} 6.9206016E7
vendor_cache_manager_default_local_container_stats_memory_used{node="infinispan-server-63198",} 5.5458032E7
vendor_cache_manager_default_local_container_stats_time_since_reset{node="infinispan-server-63198",} 130.0
vendor_cache_manager_default_number_of_cache_configurations{node="infinispan-server-63198",} 13.0
vendor_cache_manager_default_number_of_created_caches{node="infinispan-server-63198",} 2.0
vendor_cache_manager_default_number_of_running_caches{node="infinispan-server-63198",} 2.0
vendor_cache_manager_default_server_single_port_11222_transport_number_iothreads{node="infinispan-server-63198",} 16.0
vendor_cache_manager_default_server_single_port_11222_transport_number_of_global_connections{node="infinispan-server-63198",} 1.0
vendor_cache_manager_default_server_single_port_11222_transport_number_of_local_connections{node="infinispan-server-63198",} 1.0
vendor_cache_manager_default_server_single_port_11222_transport_pending_tasks{node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_server_single_port_11222_transport_total_bytes_read{node="infinispan-server-63198",} 7559.0
vendor_cache_manager_default_server_single_port_11222_transport_total_bytes_written{node="infinispan-server-63198",} 645939.0

CacheManagerレベルのものと

vendor_cache_manager_default_cache_container_health_free_memory_kb{node="infinispan-server-63198",} 13067.0
vendor_cache_manager_default_cache_container_health_number_of_cpus{node="infinispan-server-63198",} 8.0
vendor_cache_manager_default_cache_container_health_number_of_nodes{node="infinispan-server-63198",} 3.0
vendor_cache_manager_default_cache_container_health_total_memory_kb{node="infinispan-server-63198",} 67584.0
vendor_cache_manager_default_cache_container_stats_average_read_time_nanos{node="infinispan-server-63198",} 55291.0
vendor_cache_manager_default_cache_container_stats_average_read_time{node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_container_stats_average_remove_time_nanos{node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_container_stats_average_remove_time{node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_container_stats_average_write_time_nanos{node="infinispan-server-63198",} 1567124.0
vendor_cache_manager_default_cache_container_stats_average_write_time{node="infinispan-server-63198",} 1.0

〜省略〜

Cacheレベルのものは、それぞれ名前が入っているのでわかりやすいですね。

vendor_cache_manager_default_cache_distCache_cluster_cache_stats_activations{cache="distCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_approximate_entries_in_memory{cache="distCache",node="infinispan-server-63198",} 200.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_approximate_entries_unique{cache="distCache",node="infinispan-server-63198",} 100.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_approximate_entries{cache="distCache",node="infinispan-server-63198",} 200.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_read_time_nanos{cache="distCache",node="infinispan-server-63198",} 68779.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_read_time{cache="distCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_remove_time_nanos{cache="distCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_remove_time{cache="distCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_write_time_nanos{cache="distCache",node="infinispan-server-63198",} 1756830.0
vendor_cache_manager_default_cache_distCache_cluster_cache_stats_average_write_time{cache="distCache",node="infinispan-server-63198",} 1.0
〜省略〜

vendor_cache_manager_default_cache_replCache_cluster_cache_stats_activations{cache="replCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_approximate_entries_in_memory{cache="replCache",node="infinispan-server-63198",} 300.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_approximate_entries_unique{cache="replCache",node="infinispan-server-63198",} 100.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_approximate_entries{cache="replCache",node="infinispan-server-63198",} 300.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_read_time_nanos{cache="replCache",node="infinispan-server-63198",} 50003.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_read_time{cache="replCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_remove_time_nanos{cache="replCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_remove_time{cache="replCache",node="infinispan-server-63198",} 0.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_write_time_nanos{cache="replCache",node="infinispan-server-63198",} 1553920.0
vendor_cache_manager_default_cache_replCache_cluster_cache_stats_average_write_time{cache="replCache",node="infinispan-server-63198",} 1.0

〜省略〜

なお、CacheManagerの名前は今回はdefaultです。これがメトリクスの名前に反映されています。

   <cache-container name="default" statistics="true">

https://github.com/infinispan/infinispan/blob/14.0.2.Final/core/src/main/java/org/infinispan/metrics/impl/AbstractMetricsRegistration.java#L71-L76

Hot Rod Clientでメトリクスを取得する

次は、Hot Rod Clientでメトリクスを取得してみます。

テストコードはこちら。

    @Test
    public void clientMetrics() {
        String uri = createUri("ispn-user", "password");

        Configuration configuration =
                new ConfigurationBuilder()
                        .uri(uri)
                        .statistics().enable() // .jmxEnable() JMX MBeanも有効にする場合
                        .build();

        try (RemoteCacheManager manager = new RemoteCacheManager(configuration)) {
            RemoteCache<String, String> cache = manager.getCache("distCache");

            IntStream
                    .rangeClosed(1, 100)
                    .forEach(i -> cache.put("key" + i, "value" + i));

            IntStream
                    .rangeClosed(1, 50)
                    .forEach(i -> assertThat(cache.get("key" + i)).isNotNull());

            IntStream
                    .rangeClosed(101, 125)
                    .forEach(i -> assertThat(cache.get("key" + i)).isNull());

            ServerStatistics serverStatistics = cache.serverStatistics();

            serverStatistics
                    .getStatsMap()
                    .entrySet().forEach(entry -> System.out.printf("%s = %s%n", entry.getKey(), entry.getValue()));

            RemoteCacheClientStatisticsMXBean clientStatistics = cache.clientStatistics();
            assertThat(clientStatistics.getRemoteStores()).isEqualTo(100);
            assertThat(clientStatistics.getRemoteHits()).isEqualTo(50);
            assertThat(clientStatistics.getRemoteMisses()).isEqualTo(25);
        }
    }

今回は、メトリクスのみ有効にしました。JMX MBeanでアクセスしたい場合は、jmxEnableも呼び出してください。

標準出力に書き出している部分の値は、こんな感じになります。

currentNumberOfEntries = -1
globalRemoveHits = 0
removeMisses = 0
approximateEntries = 76
approximateEntriesUnique = 45
globalRetrievals = 150
stores = 90
retrievals = 58
globalHits = 100
globalRemoveMisses = 0
hits = 40
removeHits = 0
timeSinceStart = 1
globalCurrentNumberOfEntries = -1
totalNumberOfEntries = 90
misses = 18
globalMisses = 50
globalApproximateEntriesUnique = 100
globalApproximateEntries = 200
globalStores = 200

これで、Hot Rod Client側も確認できました。

Prometheusでメトリクスを取得する

最後に、PrometheusでInfinispan Serverからメトリクスを取得してみます。

Prometheusの設定は、このようにしました。

prometheus.yml

global:
  scrape_interval: 5s
  evaluation_interval: 5s

scrape_configs:
  - job_name: "infinispan-server"
    static_configs:
      - targets:
        - 172.18.0.2:11222
        - 172.18.0.3:11222
        - 172.18.0.4:11222
    basic_auth:
      username: ispn-user
      password: password
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]

Infinispan Serverの各ノードを指定しつつ、Basic認証も設定。

Prometheusを起動したら、Web UIで確認。

Targetとして認識していることを確認。

メトリクスも認識できています。

OKですね。

ソースコードを見てみる

気になる範囲で、ソースコードを見てみます。Infinispan 13.0の時にまとめたものですが、モジュールが移動していたり

JMX MBeanに関する話

メトリクスに関するインターフェースやクラスはこちら。

https://github.com/infinispan/infinispan/tree/14.0.2.Final/core/src/main/java/org/infinispan/stats

https://github.com/infinispan/infinispan/tree/14.0.2.Final/core/src/main/java/org/infinispan/stats/impl

ドキュメントとしては、こちらですね。

JMX Components

JMX MBeanの属性や操作は、以下のアノテーションで指定されているものが対象のようです。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/component-annotations/src/main/java/org/infinispan/jmx/annotations/ManagedAttribute.java

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/component-annotations/src/main/java/org/infinispan/jmx/annotations/ManagedOperation.java

これを、ビルド時にPluggable Annotation Processing APIで処理してソースコードを生成します。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/component-processor/src/main/java/org/infinispan/component/processor/ComponentAnnotationProcessor.java#L384-L407

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/component-processor/src/main/java/org/infinispan/component/processor/ComponentAnnotationProcessor.java#L409-L424

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/component-processor/src/main/java/org/infinispan/component/processor/Generator.java

というのが、JMX MBeanに関する話。

Micrometerで取得できるメトリクス

Infinispanのドキュメントでは、JMX MBeanとして扱える対象は以下ということになっています。

JMX Components

どういうことかというと。

メトリクスを登録している箇所は、以下になります。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/core/src/main/java/org/infinispan/metrics/impl/MetricsCollector.java#L140-L179

gauseとhistogramのみを対象にしていることがわかります。

これには、@ManagedAttributeアノテーションdataType属性が関係します。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/component-annotations/src/main/java/org/infinispan/jmx/annotations/ManagedAttribute.java#L44

gaugeに対応するものはMEASUREMENTで、かつ整数・小数のものみたいです。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/component-annotations/src/main/java/org/infinispan/jmx/annotations/DataType.java#L15-L20

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/component-processor/src/main/java/org/infinispan/component/processor/Generator.java#L263-L274

histogramはHISTOGRAMおよびTIMERが対応します。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/component-processor/src/main/java/org/infinispan/component/processor/Generator.java#L276-L283

https://github.com/infinispan/infinispan/blob/14.0.2.Final/build/component-annotations/src/main/java/org/infinispan/jmx/annotations/DataType.java#L22-L30

使われているのは、TIMERのみでここくらいのようですけどね。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/core/src/main/java/org/infinispan/interceptors/impl/CacheMgmtInterceptor.java#L107-L125

JMX MBeanよりも取得できるメトリクスが少ないことはわかるのですが、実際どのようなメトリクスが取得できるかは実際に動かして
確認した方が早そうですね。

ちなみに、vendorという文字列はここで付与しているようです。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/core/src/main/java/org/infinispan/metrics/impl/MetricsCollector.java#L145

baseスコープのメトリクス

baseスコープのメトリクスは、こちらで登録しているようです。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/core/src/main/java/org/infinispan/metrics/impl/BaseAdditionalMetrics.java

https://github.com/infinispan/infinispan/blob/14.0.2.Final/core/src/main/java/org/infinispan/metrics/impl/BaseMemoryAdditionalMetrics.java

https://github.com/infinispan/infinispan/blob/14.0.2.Final/core/src/main/java/org/infinispan/metrics/impl/BaseOperatingSystemAdditionalMetrics.java

vendor分も一部追加であるようですけどね。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/core/src/main/java/org/infinispan/metrics/impl/VendorAdditionalMetrics.java

このあたりは、SmallRye Metricsを使っていた時にはなかった部分ですね。

Micrometerのエンドポイント

Micrometerを使った、メトリクスを返却するエンドポイントはこちら。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/server/rest/src/main/java/org/infinispan/rest/resources/MetricsResource.java

Content-TypeでPrometheus FormatとOpenMetrics Formatの出し分けを行っているのは、こちらのようです。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/server/rest/src/main/java/org/infinispan/rest/resources/MetricsResource.java#L55-L57

Hot Rod Clientのメトリクスに関するインターフェースとクラス

Hot Rod Clientのメトリクスに関するインターフェースとクラスの組み合わせは、こちら。

インターフェース。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/client/hotrod-client/src/main/java/org/infinispan/client/hotrod/jmx/RemoteCacheClientStatisticsMXBean.java

https://github.com/infinispan/infinispan/blob/14.0.2.Final/client/hotrod-client/src/main/java/org/infinispan/client/hotrod/jmx/RemoteCacheManagerMXBean.java

https://github.com/infinispan/infinispan/blob/14.0.2.Final/client/hotrod-client/src/main/java/org/infinispan/client/hotrod/ServerStatistics.java

実装。

https://github.com/infinispan/infinispan/blob/14.0.2.Final/client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/ClientStatistics.java

https://github.com/infinispan/infinispan/blob/14.0.2.Final/client/hotrod-client/src/main/java/org/infinispan/client/hotrod/RemoteCacheManager.java

https://github.com/infinispan/infinispan/blob/14.0.2.Final/client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/ServerStatisticsImpl.java

Hot Rod Clientのメトリクスに関する、これ以上の情報はなさそうです。

まとめ

メトリクス取得の仕組みがMicrometerになった、Infinispan Serverのメトリクス取得を試してみました。Hot Rod Clientはオマケですが。

メトリクス名とか変わったのかなと思ったのですが、それほど変更はなさそうでした。

ソースコードもどう変わったか見直せましたし、今回はこんなところでしょう。

今回作成したソースコードは、こちらに置いています。

https://github.com/kazuhira-r/infinispan-getting-started/tree/master/remote-cache-metrics-micrometer