Elastic StackをDocker上で実行してログモニタリングサービスを作成するまで④ - Spring Boot編

## 背景
前回の記事の続きです！
この記事は4/4回目、最終回です。

## できること
この投稿は全４回に渡ってシリーズ化する予定です！
ほかの記事もよろしければぜひご覧ください。

1. [Elasticsearch編](https://qiita.com/sgr0416st/items/d0d00723b49c3935137e): ElasticsearchをDocker上で起動して、実際に動かしてみる
2. [Kibana編](https://qiita.com/sgr0416st/items/28dc2df02bb946f94209): KibanaをDocker上で起動して、データを可視化してみる
3. [Filebeat編](https://qiita.com/sgr0416st/items/74723ba2bb5667f5411a): Filebeatを利用して、ログファイルをKibanaで表示してみる
4. **[Spring Boot編](https://qiita.com/sgr0416st/items/3bb415783f1464aa7df6): 簡単なSpring Webアプリケーションをローカルで実行、ログを作成してそれをKibanaで可視化する**

[デモ編](https://qiita.com/sgr0416st/items/6409fb84f5463cd2112a): とりあえず完成品を動かしてみる


## Spring Bootとは
https://spring.pleiades.io/spring-boot/docs/current/reference/html/getting-started.html

> Spring Boot は、実行可能なスタンドアロンの本番レベルの Spring ベースのアプリケーションを作成できます。規約に従うことにより、Spring プラットフォームとサードパーティのライブラリを最小限の手間で使い始めることができ、ほとんどの Spring Boot アプリケーションは、Spring の設定が不要です。

込み入った設定をせずともいい感じにSpringアプリケーションが作成できるツールという認識でOKです。

## 手順

#### 前提
- 前回の記事([Elastic StackをDocker上で実行してログモニタリングサービスを作成するまで③ - filebeat編](https://qiita.com/sgr0416st/items/74723ba2bb5667f5411a))を実行済み

それでは早速デモ用のSpring Bootアプリケーションを作成していきます。
今回はアプリケーションをローカルで動かしていきますが、Spring BootもDockerで動かしてみたいという方は[こちらの記事](https://qiita.com/tkani/items/ed56229330f00a333d5e)が大変参考になりそうです！

１. **Spring Initializerから新規プロジェクトを作成**
[spring initializer](https://start.spring.io/)のページから、Spring Bootアプリケーションを作成してください(もちろん統合開発環境から直接作ってもOK)。今回は以下の様な設定にしましたが、適宜お好みで変えてください。
**依存関係にWeb, lombokを入れる**のを忘れないようにしてください。

![スクリーンショット 2021-06-27 23.49.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271486/5d5d35e5-a989-e48c-18b5-9729562d6936.png)


作成したら、プロジェクトのルートディレクトリに配置してください。
最終的に以下の様なフォルダ構成になっていると思います。

- /{projectディレクトリ}/
    - elasticsearch/
        - elasticsearch.yml 
    - filebeat/
        - config/
            - filebeat.docker.yml
        - logs/
            - logging-demo.log
        - Dockerfile
    - logging-demo/
        - ... ファイルたくさん
    - docker-compose.yml

**２. リクエストを受け付けるコントローラを作成**
com.example.{プロジェクト名}ディレクトリに"controller"という名前でパッケージを作成し、その下にコントローラークラス(この例ではDemoController)を作成しましょう。
![create controller.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271486/e4b4d918-bb24-bde1-5454-ef80c9ab177e.png)

**３. エンドポイントを作成**
次に、Getリクエストを送ったら"Helo, World"と返ってくるだけのエンドポイントを作成しましょう。
    
```DemoController.java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @GetMapping("/")
    public String getHello(){
        return "Hello, World";
    }
}
```    
    
作成したら、きちんと動くか実際にリクエストを送って確かめてみましょう。
アプリケーションを実行したあと Spring Application (http://localhost:8080) にアクセスして Hello, World と返ってくるか確認してください。
確認できたら一旦停止しておきましょう。

**４. ログを出力する**
現在の時刻と共に"return response"というメッセージをログに残すようにコードを修正しましょう。
今回はSlf4j, Logbackというライブラリを使用します。(lombokがpomファイルに記述されていれば動作します)

```DemoController.java
@RestController
@Slf4j
public class DemoController {

    @GetMapping("/")
    public String getHello(){
        log.info("{}: return response", LocalDateTime.now());
        return "Hello, World";
    }
}

```

再びアプリケーションを実行し、Spring Application (http://localhost:8080) にアクセスしてきちんとログが標準出力に表示されているか確認してください。
確認できたら再び停止しておきましょう。

ここまで出来たら、次にログファイルを生成しましょう。今回は src/main/resources/appication.yml というファイルに追記して設定を変更していきます。

```application.yml
spring.application.name={プロジェクト名}

logging.pattern.console="%clr(%d{${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${logging.pattern.level:}) %clr(${PID:}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%logger){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}"
logging.pattern.file="%d{${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}} ${logging.pattern.level:} ${PID:} --- [%t] %logger : %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}"
logging.pattern.level="%5p [${spring.application.name:},%mdc{traceId},%mdc{spanId}]"

logging.file.name=logs/${spring.application.name}.log
```

これはほぼデフォルトの設定と同じ表示形式ですが、今はおまじないみたいなものと思ってもらって構いません笑
(Spring Applicationのログについてもっと知りたい方は[こちら](https://qiita.com/tag1216/items/b898b8fb58920bf335b20))

全て終わったら今一度アプリケーションを実行し、Spring Application (http://localhost:8080) にアクセスしたあと指定したディレクトリ(src/main/resources/logs/)にログファイルがきちんと作成されているか確認してみましょう。

![create log file.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271486/cc50a9d0-ecb8-488a-68b1-fa43c660ce11.png)

お疲れ様です！
確認ができたら一旦ログファイルを消去しましょう。(logフォルダは消さないでください)
ここまででアプリケーションの準備が完了したので、仕上げにdocker-compose.ymlを少し編集していきます。

**５. filebeatが読み込むログファイルの変更**

ルートプロジェクトに戻って、docker-compose.ymlを開きましょう。
まずは、filebeat.volumes.sourceの設定を ./filebeat/logs から ./logging-demo/logs に変更します。

```docker-compose.yml
...
  filebeat:
    ...
    volumes:
      - type: bind
        source: ./logging-demo/logs
        target: /usr/share/filebeat/logs
   ..
```

最後に、filebeat/config/filebeat.docker.ymlファイルの filebeat.inputs.pathsが/usr/share/filebeat/logs/logging-demo.logになっているか確認しましょう(サンプルデータのログファイル名をlogging-demo.logにしていた方は変更の必要はありません)。

```filebeat.docker.yml
filebeat.inputs:
  - type: log
    paths:
      - /usr/share/filebeat/logs/logging-demo.log
...
```

全て完了したら、まず以下のコマンドでElastic Stackを起動させましょう。

```
docker-compose up -d
```

つづけてSpring Bootアプリケーションを実行しましょう。
その後しばらく待ってKibanaし、[前回のドキュメント]()の手順４と全く同様の手続きで、Kibana上からデータがきちんと登録されていることを確認し、index patternを設定しましょう。

最終的にKibanaのDiscoverから以下のようなグラフとログデータが表示されるところまで進めてください。
![kibana x spring boot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271486/5e95225c-d025-2f03-4c58-156b63786dfe.png)

そこまできたら、検索窓にreponseと打ち込んでrefreshしてみましょう。
このキーワードに一致するログはまだ見つからないはずです。

![response.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271486/40acdf13-7b09-2b5c-d64d-502e21bfbb02.png)

最後に、http://localhost:8080 にもう一度アクセスしてみましょう。
すると、アプリケーション側で ```yyyy-MM-ddThh:mm:ss.SSS: return response``` というようなフォーマットのログが生成され、それがKibanaに反映されるはずです。30秒程待って、もう一度Kibanaを開きrefreshボタンをクリックしてみましょう。(デフォルトではfilebeatがログを読みこむ時間は30秒おきになっています)

![final result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271486/69d5dca9-cf79-1ecb-0fd3-e2a2c1d32e68.png)

この様に検索結果が変わって新しいログを取得できた方、おめでとうございます！！
これで最終目標である「簡単なSpring Webアプリケーションをローカルで実行、ログを作成してそれをKibanaで可視化する」を達成することができました！

最後にSpringアプリケーションを停止しておきましょう。
コンテナも消去して綺麗にしておいてくださいね。

```shell
docker-compose down -v --rmi local
```

長いシリーズに渡ってこの記事を読んでくださりありがとうございました〜

### 終わりに
一つ一つは簡単でしたが、たびたび設定のミスがおきたため予想外に時間がかかってしまいました。
自分にとって未知の技術は根気よく学んでいかないとうまくいきませんね。。。

## 参考
- Spring Boot on Docker: https://qiita.com/tkani/items/ed56229330f00a333d5e
- spring initializer: https://start.spring.io/
- spring log settings: https://qiita.com/tag1216/items/b898b8fb58920bf335b2