Spring Boot＋Micrometerで取得したメトリクスを、Elasticsearchに送ってKibanaで表示する

# やりたいこと
* Spring Bootアプリケーションのメトリクスを可視化したい

[Micrometer](https://micrometer.io/)というライブラリを使用すると、アプリケーションのメトリクスを簡単に取得できるそうです。

メトリクスとは、CPUやメモリの使用状況から、Spring Bootの場合はURLへのアクセス状況などもメトリクスとしてデフォルトで取得することができます。

このあたりを見ると良いでしょう。

* [JVM and System Metrics](https://micrometer.io/docs/ref/jvm)
* [Cache Metrics](https://micrometer.io/docs/ref/cache)
* [Spring Boot / Metrics](https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#production-ready-metrics)

自分で取得する項目を追加することもできるようです。

# やったこと
* Spring BootアプリケーションにMicrometerを入れ、Elasticsearchにメトリクス送信
* Kibanaで表示

Micrometerで収集したメトリクスは、どこかのデータストアに保存することになりますが、その保存先は複数選ぶことができます。

[Micrometer Documentation](https://micrometer.io/docs)

CloudWatch、Elasticsearch、Datadog、Prometheusなどなど。

今回は、Elasticsearchにデータを入れ、それからKibanaで可視化してみることにしました。

# 環境
今回の実施環境です。

```shell
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 18.04.1 LTS
Release:	18.04
Codename:	bionic


$ 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: /path/to/.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"
```

# 対象のアプリケーション

超簡単に、小さなアプリケーションを作成します。

`pom.xml`での依存関係。

```xml
    <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-elastic</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 BootでMicrometerを使う時には、`spring-boot-starter-actuator`を追加し、メトリクスの送信先をElasticsearchにするので`micrometer-registry-elastic`を追加します。

送信間隔は、ちょっと短く5秒にしました。

src/main/resources/application.properties

```
management.metrics.export.elastic.step=5s
```

設定は、こちらを参照です。

[Micrometer Elastic](https://micrometer.io/docs/registry/elastic)

[Metrics / Supported monitoring systems / Elastic](https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#production-ready-metrics-export-elastic)

用意したアプリケーションは、このくらい。

src/main/java/com/example/micrometer/elastic/App.java

```java
package com.example.micrometer.elastic;

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

今回は`Controller`もなにも用意していませんが、Spring BootアプリケーションではMicrometerを追加した際に、Spring Web MVCなどに合わせてメトリクスを取得することができます。

# Elasticsearchのインストールと起動

`tar.gz`をダウンロードして、展開。

```shell
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.5.2.tar.gz
$ tar xf elasticsearch-6.5.2.tar.gz
$ cd elasticsearch-6.5.2
```

起動。

```shell
$ bin/elasticsearch
```

確認。

```shell
$ curl localhost:9200{
  "name" : "qd3p2vS",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "6kr__MvLRsuxV5-8d8j5UQ",
  "version" : {
    "number" : "6.5.2",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "9434bed",
    "build_date" : "2018-11-29T23:58:20.891072Z",
    "build_snapshot" : false,
    "lucene_version" : "7.5.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}
```

# Kibanaのインストールと起動

`tar.gz`をダウンロードして、展開。

```shell
$ wget https://artifacts.elastic.co/downloads/kibana/kibana-6.5.2-linux-x86_64.tar.gz
$ tar xf kibana-6.5.2-linux-x86_64.tar.gz
$ cd kibana-6.5.2-linux-x86_64
```

起動。

```shell
$ bin/kibana
```

`http://localhost:5601`にアクセスすると、Kibanaが確認できます。

![範囲を選択_116.png](https://qiita-image-store.s3.amazonaws.com/0/309669/21511b4e-c565-a298-77a8-bedaf832ab89.png)

# アプリケーションを起動して、メトリクスを可視化してみる

起動。

```shell
$ mvn spring-boot:run 
```

起動した後は、Kibanaにアクセスしてみます。

すでに、「metrics-yyyy-mm」というインデックスにメトリクスが送信されているので、「
Discover」でこれを登録します。

![範囲を選択_117.png](https://qiita-image-store.s3.amazonaws.com/0/309669/4f1ef53c-a065-465c-e450-ab065acd2459.png)

時間のフィールドは`@timestamp`ですね。

![範囲を選択_118.png](https://qiita-image-store.s3.amazonaws.com/0/309669/3fd176e2-68ed-18b5-43b1-1f22e31b3756.png)

「Discover」で見ると、送信されたデータを見ることができます。

![範囲を選択_122.png](https://qiita-image-store.s3.amazonaws.com/0/309669/9429d99b-2880-2cd4-c75e-797aa4cf1a9f.png)

では、「Visualize」を選んで表示してみましょう。

今回はJavaVMのメモリについて、可視化してみます。

Y軸は`value`の`Average`で、X軸は`Date Histgram`、フィールドは`@timestamp`、インターバルは`Minite`で絞り込み。

![範囲を選択_121.png](https://qiita-image-store.s3.amazonaws.com/0/309669/a672d741-dab3-41c6-3b2c-de0ed2bc6b74.png)

X軸は、さらに`Filters`をかけて`name: jvm_memory_used`で表示対象のメトリクスを絞り込みました。

![範囲を選択_121.png](https://qiita-image-store.s3.amazonaws.com/0/309669/9ebb543a-2e36-44f9-fa93-6dbad14a09f0.png)

それっぽく表示されました。