Spring Boot Actuatorで開発の効率化を図ってみた

Springで開発していると裏側で登録されている情報を確認したくなることが多々あります。
ちゃんと意図通りにコンポーネントスキャンされてBeanが登録されているか、プロパティの設定値が登録されているか…などなど知りたいことがたくさんです。
デバッグ用にログ出力させる、なども一つの手ですがなかなか面倒に感じてしまうと思います。

そんなときにオススメなのが**Spring Boot Actuator**です。
今回はじめて使ってみて便利だと思ったので、備忘録として投稿しました。

## Spring Boot Actuatorとは？

Spring Bootで提供されている監視や管理、また開発時にも役立つ情報を取得することができます。
アプリケーションに組み込むことでHTTP/JMXから取得が可能です。
情報を取得するためのエンドポイントや細かな設定は[リファレンス](https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html)にズラッと記載されています。

## 使えるようにしてみよう！

まずは動くように組み込んでみることにします。
単純に動作させるのは依存関係を定義するだけなので、至って簡単に使うことができます。

```xml
<!-- Mavenの場合 -->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>
```

依存関係を追加した後、Spring Bootアプリケーションを起動して以下のようなcurlコマンドを実行すると有効なエンドポイントをJSON形式で確認することができます。
ブラウザ上で実行しても同様です。

```bash
$ curl -XGET localhost:8080/actuator
{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false},"health":{"href":"http://localhost:8080/actuator/health","templated":false},"health-path":{"href":"http://localhost:8080/actuator/health/{*path}","templated":true},"info":{"href":"http://localhost:8080/actuator/info","templated":false}}}
```

Actuatorを利用する際のPrefixはデフォルトで「/actuator」となっていますが設定することで変更可能です。
ポート番号もActuator専用に設定することができます。

```properties
# Actuatorを利用する際のPrefix
management.endpoints.web.base-path=/admin
# Actuatorを利用する際のポート番号
management.server.port=9999
```

使用できるエンドポイントはデフォルトの状態では`health`と`info`しか有効化されていない状態になっています。
これらを有効化するためには別途設定が必要になります。

一律有効化させたい場合は以下のように設定することで有効にできます。

■application.properties

```properties
management.endpoints.web.exposure.include=*
```

設定後に再度エンドポイントを確認すると、有効化されているものが増えていることが確認できます。
結構たくさんになりました。

```bash
$ curl -XGET localhost:8080/actuator/
{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false},"beans":{"href":"http://localhost:8080/actuator/beans","templated":false},"caches-cache":{"href":"http://localhost:8080/actuator/caches/{cache}","templated":true},"caches":{"href":"http://localhost:8080/actuator/caches","templated":false},"health":{"href":"http://localhost:8080/actuator/health","templated":false},"health-path":{"href":"http://localhost:8080/actuator/health/{*path}","templated":true},"info":{"href":"http://localhost:8080/actuator/info","templated":false},"conditions":{"href":"http://localhost:8080/actuator/conditions","templated":false},"shutdown":{"href":"http://localhost:8080/actuator/shutdown","templated":false},"configprops":{"href":"http://localhost:8080/actuator/configprops","templated":false},"env-toMatch":{"href":"http://localhost:8080/actuator/env/{toMatch}","templated":true},"env":{"href":"http://localhost:8080/actuator/env","templated":false},"loggers-name":{"href":"http://localhost:8080/actuator/loggers/{name}","templated":true},"loggers":{"href":"http://localhost:8080/actuator/loggers","templated":false},"heapdump":{"href":"http://localhost:8080/actuator/heapdump","templated":false},"threaddump":{"href":"http://localhost:8080/actuator/threaddump","templated":false},"metrics-requiredMetricName":{"href":"http://localhost:8080/actuator/metrics/{requiredMetricName}","templated":true},"metrics":{"href":"http://localhost:8080/actuator/metrics","templated":false},"scheduledtasks":{"href":"http://localhost:8080/actuator/scheduledtasks","templated":false},"mappings":{"href":"http://localhost:8080/actuator/mappings","templated":false}}}
```

上記の例ではエンドポイントを全て公開していますが、本来使用するものだけ有効化にするのが安全です。
もともとActuatorのエンドポイントはデフォルトでセキュリティの保護対象でしたが、Spring Boot 2.0からは保護対象ではなくなっています。
そのため、管理者のみがエンドポイントに安全にアクセスできるよう個別にSpring Securityの設定が必要となります。

それ以外には設定で明示的に公開したくないエンドポイントを指定することでアクセスできなくすることも可能です。

■application.properties

```properties
management.endpoints.web.exposure.exclude=env
```

## 実用的に使えそうなもの

私自身が普段開発に携わっているということもあり、開発に活かせるものとしてはどれなんだろう…と思っていろいろ試してみました！

### beans

アプリケーション内に登録されているBeanの一覧を確認することができます。
(Spring Bootでは特にAutoConfigrationで登録されたBeanが無数に表示されてしまいますが…)

登録されているBeanのスコープも同時に確認することができるので、意図したスコープで登録されていないことによって事故が起こるリスクを未然に防ぐことができると思います。

### env

Enviromentオブジェクトに登録されているプロパティの値を一覧で確認することができます。
動作環境によって設定値を切り替えている環境などでは正常に切り替わっているか確認することができるので、非常に便利です。

ただ一点注意するポイントとしては、設定値にIPアドレスやユーザー / パスワードなどの情報を含んでいる可能性があることです。
これらは当然ながら外部に公開されていいものではないので、エンドポイントをセキュリティで保護するかそもそも有効化しないのがベストだと思います。

### mappings

`@RequestMapping`で定義しているアクセスポイントを一覧で確認することができます。
404などでアクセスできない場合などの調査に役立つと思いました。
アクセスポイントとして登録されていなかった際は、Controllerクラスが正常にコンポーネント登録されているか？など確認してみるのが良さそうです。

### loggers

アプリケーションが動作している状態のままログレベルの確認・変更が可能です。
開発においては必要なログレベルを調節したり、不要なログを出力したくない場面はあると思うので、かなり実用的です。

例えばLogbackでSpring側で出力されるログレベルを以下のようにINFOに設定していたとします。

```xml
<logger name="org.springframework" level="INFO">
	<appender-ref ref="console" />
</logger>
```

この設定状態でアプリケーションを起動し、エンドポイントからログレベルを確認するとINFOであることが確認できます。
`effectiveLevel`が実際に適用されているログレベルになります。

```bash
$ curl -XGET localhost:8080/actuator/loggers/org.springframework
{"configuredLevel":"INFO","effectiveLevel":"INFO"}
```

仮に、このログレベルがINFOの状態からDEBUGに変えたいという場合もエンドポイントポイントへアクセスすることで変更が可能です。
以下のようにPOSTでアクセスすることで変更することができます。

```bash
$ curl -XPOST localhost:8080/actuator/loggers/org.springframework -H "Content-Type: application/json" -d"{\"configuredLevel\": \"DEBUG\"}"
```

再度ログレベルを確認するとDEBUGに変更されていることが確認できます。

```bash
$ curl -XGET localhost:8080/actuator/loggers/org.springframework
{"configuredLevel":"DEBUG","effectiveLevel":"DEBUG"}
```

### health

シンプルではありますが、アプリケーションのヘルス情報表示されます。

```bash
$ curl -XGET localhost:8080/actuator/health
{"status":"UP"}
```

### shutdown

あまり開発では使用しないかもしれないですが、エンドポイントを経由してアプリケーションを停止することができます。
有効化するには`shutdown`のみ別途設定が必要になります。

■application.properties

```properties
management.endpoint.shutdown.enabled=true
```

有効化している状態で以下を実行するだけで停止することができます。

```bash
$ curl -XPOST localhost:8080/actuator/shutdown
{"message":"Shutting down, bye..."}
```

アクセス一つで停止することができるため、有効化する場合はセキュリティの保護設定は管理者のみ操作可能となるように厳しくする必要があります。
または必要がない場合はエンドポイント自体を無効にしていた方が良さそうです。
誰でもアプリケーションを停止できる状態になってしまうのは非常におそろしいことなので…

## まとめ

監視や管理の観点で便利であるだけでなく、開発者にとっても非常にメリットが多いと使ってみて感じました。
これまで確認したいときに見えにくかった情報が可視化されているため、有用性は高いと思います。

普段Spring BootよりもMVCで開発することが多いのですが、取り入れる機会があれば実際に案件でも利用していきたいです。
エンドポイントはこの記事で紹介しきれないくらいあるので、他に気になるものがあれば有効化して使っていきます。

## 参考

https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html

https://speakerdeck.com/rshindo/jsug-2019-08