日々常々

ふつうのプログラマがあたりまえにしたいこと。

SpringBoot3.4で構造化ログが標準でできるようになると聞いて

SpringBootでのサーバーアプリケーションはもうコンテナ運用も当たり前で、コンテナ運用が当たり前ってことはログも生ログファイルを見るんじゃなくどこかに集められたものを見るのが当たり前で、複数のサーバーで運用されるログを集約してみる場合は何かしら横断的にログを検索する項目があるのも当たり前で、集約システムとか挟むんだからログもパースできるのが当たり前で。

いろんな事情に後押しされて、現代のサーバーアプリケーションは構造化ログを出すのが当たり前です。 SpringBootで構造化ログを出力する場合、現段階ではECS LoggingやLogstash Logback Encoderなどを使用するのが一般的でしょう。

ECS Loggingとかの話

「ECS Logging」と言うとコンテナ運用の話もあいまって「Amazon ECSのログのこと?」となり「うちAWSじゃないしなぁ」とか「Amazon ECS使ってるけどAWS依存させたくないなぁ」とかの反応もしばしばありますが、このECSはElasticCommonSchemaで、Elasticsearch文脈です。

github.com

ECS LoggingはElasticsearchを使用する場合にはもちろん使えますが、別にElasticsearchを使わなくても(たとえばAmazon CloudWatch LogsやDatadogなど)、JSONの構造化ログをパースできるものであれば使えます。

Logstash Logback Encoderも似たようなもん。名前の通りLogback用なので、Log4j2とかを使うならあったものを探したりする感じです。

github.com

で、これらはSpringBootの外のライブラリであり、独自に依存を追加する必要があります。 また、SpringBootの依存管理対象外のため、バージョンも自身で面倒を見る必要があります。 地味に面倒臭いですが、必要なので仕方なく面倒を見ていました。しばしば忘れられがちでもあります。

SpringBoot3.4から追加ライブラリなしで構造化ログを出力できるようになる

本題。冒頭のポストの通り、SpringBoot3.4.0でSpringBoot自身が構造化ログをサポートするようです。詳しくは以下のSpringのブログを見てください。

spring.io

ここでは logging.structured.format.console=ecs を書いていますが logging.structured.format.console=logstash もOKです。ブログの通りECSとLogstash、つまり ecslogstash の二値がサポートされているようです。

hogeを指定して怒られた図

マイルストーンリリースの使い方

GradleやMavenでSpringのマイルストーンリリースを使用する場合、(おそらく普段使用しているであろう)MavenCentralRepositoryにはないのでマイルストーンリポジトリの参照を追加してやる必要があります。

Springのマイルストーンリポジトリhttps://repo.spring.io/milestone です。 (Springの公式ドキュメントにも書いてるんだけど、探すの面倒だったので割愛)

Gradleではbuild.gradle.ktsrepositories に追加すればOK

repositories {
    mavenCentral()
    maven {
        url = uri("https://repo.spring.io/milestone")
    }
}

どうでもいいけどIntelliJさんの補完がこれを候補にだしてくれて、やっぱみんな追加するのSpringなんだなぁってなりました。

「どうせ追加するのSpringでしょ?」と言われてる図

で、これだけだと動かない。 なぜならSpringBootプラグインを使ってるので、プラグインの使うリポジトリも追加してやる必要がある。 こっちは build.gradle.kts よりも前に解決されなきゃなので settings.gradle に書きます。

pluginManagement {
    repositories {
        gradlePluginPortal()
        maven {
            url = uri("https://repo.spring.io/milestone")
        }
    }
}

SpringBootGradlePluginのバージョンを 3.4.0-M2 にする。

plugins {
    java
    id("org.springframework.boot") version "3.4.0-M2"
}

これでOK。 ちゃんと意図したバージョン使われてるかは確認しとこーね。

あとは logging.structured.format.console プロパティいじったり、 gradle dependencies で依存ライブラリ見たり、実装コード追って見たり、ブログ参照しながらLogWriterカスタマイズしたり、するとよい。

SpringBoot3.4以降の対応

稼働中のアプリケーションの場合、現在使用している構造化ログがいきなりつかえなくなるわけでもないので、現在使用しているものがあるなら別段慌てる必要はありません。 構造化ログの項目追加などカスタマイズしている場合は対応内容も変わるでしょう。 ログ出力周りは性能などの兼ね合いもあります。動いているなら私なら特に慌てません。何か機会があればちょっと見てみるかーくらいの温度感で対応すると思います。

一方、新規であれば「ECS LoggingかLogstash Logback Encoderなどを検討する」の前に「SpringBoot標準機能のこれで十分だったりしないかな?」を検討すると思います。 新規でなくてもログのカスタマイズなど手を入れていなくて単に構造化だけをやっている、まだ構造化ログにできていない、などの段階であれば、とりあえずプロパティ有効にしてみるとかもありだと思います。 こだわりのない依存ライブラリ管理は一つでも減らせるに越したことはないです。

そんな感じ。