基本的な使い方のサンプルコード
plugins { id 'java' id 'org.springframework.boot' version '3.3.1' id 'io.spring.dependency-management' version '1.1.5' } group = 'com.example' version = '0.0.1-SNAPSHOT' java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'net.logstash.logback:logstash-logback-encoder:7.4' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { useJUnitPlatform() }
logstash-logback-encoder
のバージョンはspring-boot、というより、これに含まれるlogbackに合わせる必要がある……らしい。詳細は https://github.com/logfellow/logstash-logback-encoder?tab=readme-ov-file#including-it-in-your-project にある。問題があると実行時にClassNotFoundException
などが発生したりするらしい。
src/main/resources/logback-spring.xml
を作成する。
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="net.logstash.logback.encoder.LogstashEncoder"> </encoder> </appender> <root level="INFO"> <appender-ref ref="CONSOLE"/> </root> </configuration>
動作確認用の適当なRestController
を作成する。
@SpringBootApplication @RestController @Slf4j public class App { @GetMapping("/test") public String ho() { log.info("info"); log.error("", new NullPointerException("error")); return "sad"; } public static void main(String[] args) { SpringApplication.run(App.class, args); } }
これでログがjsonになるが、開発中は見やすく整形して表示する設定を追加する。
<encoder class="net.logstash.logback.encoder.LogstashEncoder"> <jsonGeneratorDecorator class="net.logstash.logback.decorate.PrettyPrintingJsonGeneratorDecorator"/> ...(略)
実行例。
{ "@timestamp" : "2024-07-14T19:58:24.6156441+09:00", "@version" : "1", "message" : "info", "logger_name" : "org.example.app.App", "thread_name" : "http-nio-8080-exec-6", "level" : "INFO", "level_value" : 20000 } { "@timestamp" : "2024-07-14T19:58:24.6156441+09:00", "@version" : "1", "message" : "", "logger_name" : "org.example.app.App", "thread_name" : "http-nio-8080-exec-6", "level" : "ERROR", "level_value" : 40000, "stack_trace" : "java.lang.NullPointerException: error\r\n\t(略)" }
LoggingEvent
上記を基本形にドキュメントみながらあれこれ修正を加えていく。ここでは幾つかのみ触れる。
https://github.com/logfellow/logstash-logback-encoder?tab=readme-ov-file#loggingevent-fields
フィールド名の変更
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="net.logstash.logback.encoder.LogstashEncoder"> <jsonGeneratorDecorator class="net.logstash.logback.decorate.PrettyPrintingJsonGeneratorDecorator"/> <fieldNames> <timestamp>時間</timestamp> <stackTrace>stacktrace</stackTrace> </fieldNames> </encoder> </appender>
試しに日本語にしてみたが特に意味はない。
{ "時間" : "2024-07-13T19:12:05.2237172+09:00", (略) "stacktrace" : "java.lang.NullPointerException: (略)" }
key-valueでフィールド追加
https://github.com/logfellow/logstash-logback-encoder?tab=readme-ov-file#key-value-pair-fields
https://www.slf4j.org/manual.html#fluent とかいうのでkey/valueペアを仕込める。以下のようにすると、
log.atInfo().addKeyValue("fluent-key", "fluent-value").setMessage("fluent-msg").log();
以下のようなフィールドが追加される。
"fluent-key" : "fluent-value"
以下のようにしてinclude/excludeを切り替えられる。たいていの項目は<exclude...>
, <include...>
という形式で切り替えられる。
<excludeKeyValueKeyName>fluent-key</excludeKeyValueKeyName>
この設定項目に関しては以下で全部出なくなる。
<includeKeyValuePairs>false</includeKeyValuePairs>
StructuredArguments/Markers
StructuredArguments
, Markers
でフィールド追加できる。細かい違いについては上記ドキュメントを参照。
StructuredArguments
の例。
log.info("log message {}", StructuredArguments.value("name", "value"));
"message" : "log message value", "name" : "value",
Markers
の例。
log.info(Markers.append("marker-name", "v"), "log");
"message" : "log", "marker-name" : "v",
LoggingEventCompositeJsonEncoder でより細かくJSONフォーマットを指定
https://github.com/logfellow/logstash-logback-encoder?tab=readme-ov-file#composite-encoderlayout
以下は使用例。%..
は https://logback.qos.ch/manual/layouts.html#ClassicPatternLayout を参照。
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"> <providers> <timestamp/> <pattern> <pattern> { "message": "%msg", "exception-message": "%ex{0}" } </pattern> </pattern> </providers> </encoder>
実行例。
{"@timestamp":"2024-07-14T20:33:21.110684+09:00","message":"info","exception-message":""} {"@timestamp":"2024-07-14T20:33:21.110684+09:00","message":"","exception-message":"java.lang.NullPointerException: error\r\n"}