CLOVER🍀

That was when it all began.

Spring Boot+Micrometerでメトリクス取得から、Prometheus/Grafanaを使ったグラフ表示まで

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

  • メトリクスやモニタリングまわりにあまり勘所がないので、少しずつ試してみようと
  • Spring Bootを使っていると、Micrometerというものが便利らしいので、まずはこれを
  • メトリクスの収集にはPrometheusを、可視化にはGrafanaを試してみようと

全部に言えますが、「初めてやってみました」エントリです。

Spring BootにMicrometerを入れ、Prometheusでメトリクスを収集し、Grafanaで可視化するまでの最低限のことを
やっていきます。

Micrometer?

Micrometerとは、Javaでメトリクスを取得できるようにするベンダー非依存のライブラリです。

Micrometer Application Monitoring

Prometheus、AWS CloudWatch、Datadog、New Relicなど、いろいろなメトリクス収集・モニタリング・監視ソフトウェア、サービスに
取得したメトリクスを送信したりできるようになります。

Spring Bootで使うと、これが非常に簡単に使えるようになるらしいです。

Spring Boot 2.0 でモニタリング 〜Micrometer〜 - Qiita

Spring Boot で micrometer を使ってメトリクスを計測・送信する - k11i.biz

Spring BootアプリのメトリクスをMicrometerで収集する #micrometer · matsumanaの技術メモ

Spring Boot Actuator 2.0 & Micrometer

Prometheus?

Prometheusは、メトリクス収集や監視を行うソフトウェアです。

Prometheus - Monitoring system & time series database

メトリクスの収集は、Prometheusから対象へPullする(取得しに行く)方向になります。

10分で理解する Prometheus - Qiita

可視化や、アラート通知も可能なようです。

Grafana?

Grafanaは、メトリクスなどを可視化し、アラート通知なども行えるソフトウェアです。

Grafana - The open platform for analytics and monitoring

可視化などの元なるデータの取得先となるソフトウェアは、いろいろと対応しているようです。

Prometheus、AWS CloudWatch、Elasticsearch、Datadog、MySQLPostgreSQLなどなど…。

Plugins / Data Source

10分で理解するGrafana - Qiita

Grafana に入門しよう! - Qiita

オープンソースの運用管理・運用自動化 / Grafanaとは

ダッシュボードを作ることができ、そこでグラフなどの表示ができます。

合わせて

で、このあたりを組み合わせて運用していくわけですね。

Micrometer/Prometheusによる大規模システムモニタリング #jsug #sf_26

PrometheusとGrafanaを組み合わせて監視用ダッシュボードを作る | さくらのナレッジ

prometheusとgrafanaを入れたみたが、どうグラフとか出すといいのか? - Qiita

prometheus のデータを grafana でグラフ表示してみた - Qiita

Prometheus+Grafanaでパフォーマンス監視をしています - Keepdata Blog

ここからは、最初に書いたとおり、Micrometer、Prometheus、Grafanaを使って、あまり難しいこと(カスタマイズ、拡張とか)を
考えずに、最低限これらをつなげて可視化できるまでを目標にしていきます。

環境

稼働させるアプリケーション、サーバーは、いずれもDocker上で行うものとします。

IPアドレスとしては、

  • Spring Boot+Micrometer … 172.17.0.2
  • Prometheus … 172.17.0.3
  • Grafana … 172.17.0.4

としたいと思います。

Java側の環境は、こちら。

$ java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-0ubuntu0.18.04.1-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)


$ mvn -version
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 1.8.0_191, vendor: Oracle Corporation, runtime: /usr/lib/jvm/java-8-openjdk-amd64/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-39-generic", arch: "amd64", family: "unix"

PrometheusとGrafanaは、Dockerを使って立ち上げることにしましょう。

prom/prometheus

grafana/grafana

Prometheusのバージョンは2.5.0、Grafanaのバージョンは5.3.4を使用します。

Spring Boot+Micrometerのアプリケーションを用意する

では、まずはメトリクス収集対象となる、Spring Boot+Micrometerを使ったアプリケーションを書いていきましょう。

Maven依存関係などは、こちら。

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.1.1.RELEASE</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

アプリケーションは、Spring Web MVCで書くことにします。

Spring BootでMicrometerを使うには、「spring-boot-starter-actuator」とメトリクスを収集するソフトウェアに応じた
「micrometer-registry-〜」が必要です。今回は、Prometheusを使うので「micrometer-registry-prometheus」を加えます。

Spring Boot Actuator: Production-ready features

Metrics

Micrometer Prometheus

https://github.com/micrometer-metrics/micrometer-samples-spring-boot/blob/master/build.gradle

Micrometerを依存関係に加えた時に、追加される情報はこのあたりを見るのではないでしょうか。

https://github.com/micrometer-metrics/micrometer/tree/v1.1.1/micrometer-core/src/main/java/io/micrometer/core/instrument/binder

https://github.com/spring-projects/spring-boot/tree/v2.1.1.RELEASE/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics

Spring Web MVCを使った場合に取得できるメトリクスも、追加されます。

では、起動クラスとControllerを作成。
src/main/java/org/littlewings/spring/micrometer/App.java

package org.littlewings.spring.micrometer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String... args) {
        SpringApplication.run(App.class, args);
    }
}

とりあえず、動くコードがあれば良いくらいの感じなので、単純なもので。
src/main/java/org/littlewings/spring/micrometer/HelloController.java

package org.littlewings.spring.micrometer;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("hello")
public class HelloController {
    @GetMapping
    public String message() {
        return "Hello World!!";
    }
}

また、Spring Boot Actuatorのエンドポイントで、Prometheus向けのものを有効にしておく必要があります。
src/main/resources/application.properties

management.endpoints.web.exposure.include=prometheus

Exposing Endpoints

あとは、パッケージングして起動。

$ mvn package

実行は、Dockerコンテナ内で。

$ java -jar target/micrometer-prometheus-0.0.1-SNAPSHOT.jar

これで、監視対象のアプリケーション側の準備は完了です。

確認。

$ curl 172.17.0.2:8080/hello
Hello World!!

また、Prometheus向けのエンドポイントにアクセスすると、いろいろとメトリクスを取得することができます。

$ curl 172.17.0.2:8080/actuator/prometheus
# HELP tomcat_servlet_error_total  
# TYPE tomcat_servlet_error_total counter
tomcat_servlet_error_total{name="default",} 0.0
tomcat_servlet_error_total{name="dispatcherServlet",} 0.0
# HELP tomcat_threads_config_max_threads  
# TYPE tomcat_threads_config_max_threads gauge
tomcat_threads_config_max_threads{name="http-nio-8080",} 200.0
# HELP jvm_threads_states_threads The current number of threads having NEW state
# TYPE jvm_threads_states_threads gauge
jvm_threads_states_threads{state="runnable",} 7.0
jvm_threads_states_threads{state="blocked",} 0.0
jvm_threads_states_threads{state="waiting",} 12.0
jvm_threads_states_threads{state="timed-waiting",} 4.0
jvm_threads_states_threads{state="new",} 0.0
jvm_threads_states_threads{state="terminated",} 0.0
# HELP tomcat_sessions_rejected_sessions_total  
# TYPE tomcat_sessions_rejected_sessions_total counter
tomcat_sessions_rejected_sessions_total 0.0
# HELP system_cpu_count The number of processors available to the Java virtual machine
# TYPE system_cpu_count gauge
system_cpu_count 8.0
# HELP jvm_gc_memory_promoted_bytes_total Count of positive increases in the size of the old generation memory pool before GC to after GC
# TYPE jvm_gc_memory_promoted_bytes_total counter

... 省略

Spring Web MVC関連の情報は、「http_server_requests_〜」に入っています。

$ curl -s 172.17.0.2:8080/actuator/prometheus | grep http_server_requests
# HELP http_server_requests_seconds  
# TYPE http_server_requests_seconds summary
http_server_requests_seconds_count{exception="None",method="GET",outcome="SUCCESS",status="200",uri="/hello",} 1.0
http_server_requests_seconds_sum{exception="None",method="GET",outcome="SUCCESS",status="200",uri="/hello",} 0.096711315
http_server_requests_seconds_count{exception="None",method="GET",outcome="SUCCESS",status="200",uri="/actuator/prometheus",} 5.0
http_server_requests_seconds_sum{exception="None",method="GET",outcome="SUCCESS",status="200",uri="/actuator/prometheus",} 0.109337835
# HELP http_server_requests_seconds_max  
# TYPE http_server_requests_seconds_max gauge
http_server_requests_seconds_max{exception="None",method="GET",outcome="SUCCESS",status="200",uri="/hello",} 0.096711315
http_server_requests_seconds_max{exception="None",method="GET",outcome="SUCCESS",status="200",uri="/actuator/prometheus",} 0.083914304

各エンドポイントに関する、アクセス回数などがわかりますね。

Prometheusを起動して、アプリケーションのメトリクスを収集する

続いて、Prometheusを準備します。

Prometheusがメトリクスの情報をPullしてくる先を、設定として定義します。先ほど作成した、Spring Bootアプリケーションの
Prometheus向けのエンドポイントを定義しています。
prometheus.yml

scrape_configs:
  - job_name: 'spring-boot-app'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['172.17.0.2:8080']

このあたりは、こちらを参考に作成しました。

Prometheus

https://github.com/prometheus/prometheus/blob/v2.5.0/documentation/examples/prometheus.yml

これで、PrometheusのDockerコンテナを起動。

Installation | Prometheus

$ docker container run -it --rm --name prometheus -v `pwd`/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus:v2.5.0

「http://[Prometheusが動作しているホスト]:9090」にアクセスすると、UIを見ることができます。

f:id:Kazuhira:20181201225054p:plain

テキストフィールドにPrometheusのクエリを入力すると補完が効き、「Execute」ボタンを押すと「Console」に表示されます。

f:id:Kazuhira:20181201225253p:plain

「Graph」タブを押すことで、グラフも見ることができます。

f:id:Kazuhira:20181201225332p:plain

PrometheusでAlertも設定できるようですが、今回はここまでで。

f:id:Kazuhira:20181201225424p:plain

Prometheusの準備は、これでおしまいです。

Grafanaを起動して、可視化する

最後は、Grafana。

ドキュメントを参考にして、Dockerコンテナで起動します。

Installing using Docker | Grafana Documentation

$ docker container run -it --rm --name grafana grafana/grafana:5.3.4

起動したら、「http://[Grafanaが動作しているホスト]:3000」にアクセスすると、ログイン画面が表示されます。

f:id:Kazuhira:20181201225728p:plain

初期のアカウント / パスワードは、「admin / admin」なようなので、それでログイン。この時、パスワードの変更を求めらるので、
適宜変更。

このデフォルトの情報がどこに書かれているかというと、こちら。「admin_user」、「admin_password」というやつですね。

security

Home Dashboardという画面に移るので

f:id:Kazuhira:20181201230006p:plain

緑色で表示されている「Add data source」ボタンを押して、データソースを追加しましょう。

ここでは、「Type」に「Prometheus」を選択して、「Name」を適当に設定。「HTTP」の「URL」は、Prometheusにアクセス
するためのURLを設定してください。

f:id:Kazuhira:20181201230136p:plain

今回、Prometheusは「172.17.0.3」で稼働しているので、「http://172.17.0.3:9090」で設定。

その他の設定は、ここではそのままにしてページの下の方にある「Save & Test」ボタンを押します。

f:id:Kazuhira:20181201230343p:plain

これで、データソースが追加されます。

続いて、左側にある「+」ボタンを押すと、ダッシュボードが追加されます。

f:id:Kazuhira:20181201230514p:plain

ここで表示されている、「Graph」を押してダッシュボードにグラフを追加します。

空のグラフが表示されるので、タイトルをクリックするとメニューが展開されます。「Edit」を選択。

f:id:Kazuhira:20181201230804p:plain

グラフの編集画面に移るので、「Data Source」に「prometheus」を選択して、フィールドにPrometheusのクエリを
入力します。

f:id:Kazuhira:20181201230925p:plain

とはいえ、ここでは取得したメトリクスの名前そのままですが。

ここまでの操作は「Metrics」タブでしたが、今度は「General」タブに移ってグラフの名前を変更しておきましょう。

f:id:Kazuhira:20181201231104p:plain

あとは、ダッシュボードを保存します。名前は、適当に。

f:id:Kazuhira:20181201231247p:plain

f:id:Kazuhira:20181201231256p:plain

ダッシュボードに、グラフが追加されました!

f:id:Kazuhira:20181201231356p:plain

グラフをもうひとつ追加してみましょう。

f:id:Kazuhira:20181201231509p:plain

また空のグラフが表示されるので、同じ要領で「Edit」して、Prometheusから情報を取得するように編集します。

今度は、HTTPの呼び出し回数でも。

f:id:Kazuhira:20181201231655p:plain

これだと、Prometheusがメトリクスを収集するためのアクセスも見えてしまって、ジャマなように思います。

Prometheusのクエリでフィルタリングしてみましょう。

Querying basics | Prometheus

こうしました。

http_server_requests_seconds_count{uri!="/actuator/prometheus"}

スッキリですね。

f:id:Kazuhira:20181201231833p:plain

ダッシュボードを保存して、おしまい。

f:id:Kazuhira:20181201231932p:plain

とりあえず、全部つながったようです…。

まとめ

特に応用的なことはなにも考えずに、とにかくSpring Boot+Micrometer、Prometheus、Grafanaをつなげることを目標に、
いろいろ頑張ってみました。

最初はPrometheusやGrafanaがとっかかりが全然わからなかったのですが、試したり調べたりしていたら、だんだんドキュメントも
読めそうな感じになってきたので、少しずつ習熟したいなぁと思います。