Spring Bootで日別にログ出力する方法(Logback)
Spring BootでLogbackを使って日別にログ出力する方法です。
Spring Bootでは、デフォルトでコンソールにログが出力されます。ルートのログレベルは [INFO] となっており、application.yml でプロパティを設定することで簡単に利用できます。
しかし設定が簡単な反面、できることは限られてしまいます。デフォルトでは、ログファイルのサイズが10MBになったらローテートするようになっておりますが、日別にログを出力して一定期間保持したいというのが一般的な運用方法ではないでしょうか。
このように、ログ出力をカスタマイズしたい場合には Logback を使うことで解決できます。XML を作成するので、プロパティ設定よりは面倒ですが、デフォルトの設定ファイルをインクルードすることができるので、記述内容は最小限にすることができます。
ここでは Logback を使って日別にログ出力する方法 を紹介します。
環境
- Spring Boot 1.4.1
- Windows7
- Java8
- Eclipse 4.6 Neon
プロパティ設定でできること
まずはログ出力の基本情報を抑えておきましょう。
下記のプロパティを設定ファイルに追記することで、ログファイルの出力を指定できます。設定ファイルについては「Spring Bootで設定ファイル(yaml)を読み込む方法」を参照ください。
プロパティ | 説明 |
---|---|
logging.file | ログファイルのパスとファイル名を指定。ファイル名だけの指定も可(この場合カレントディレクトリににログが出力される)。 例) logs/aplname.log |
logging.path | ログファイルの出力先ディレクトリを指定。ファイル名は spring.log となる。 例) logs |
この2つは同時に指定できず logging.file が優先されます。
ログレベルは logging.level プロパティに、カテゴリ名を付加して指定します。
ルートのログレベルを指定するなら logging.level.root: INFO となり、org.springframework カテゴリのログレベルを指定するなら logging.level.org.springframework: WARN などとなります。
logging:
path: logs
level:
root: INFO
org:
springframework:
web: WARN
hibernate: ERROR
aplcategory: DEBUG
aplcategoryは作ったアプリのカテゴリを指定します。
Logbackを設定して日別にログ出力
日別にログ出力するためには、logback.xmlを記述しますが、Spring Boot の logback 設定をインクルードして利用します。
spring-boot.バージョン.jar 内の org/springframework/boot/logging/logback にある4つの XML ファイルがデフォルトとなっています。
ファイル名 | 説明 |
---|---|
base.xml | ルートとなるファイル。このファイルから各 XML ファイルをインクルードしている。 |
defaults.xml | 書式のプロパティや各ライブラリのログレベルが定義されている。 |
console-appender.xml | コンソール出力の設定が定義されている。 |
file-appender.xml | ファイル出力の設定が定義されている。 |
これらを踏まえて XML ファイルを定義します。尚、設定ファイルは logback.xml という同名ファイルではなく、logback-spring.xml という Spring っぽい名前にしています。
・logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<!-- Spring Bootデフォルト設定読込 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<!-- 開発環境では、INFO レベル以上を console に出力する -->
<springProfile name="dev">
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<!-- テスト・本番環境では、INFO レベル以上を ファイル に出力する -->
<springProfile name="test, production">
<include resource="logback-file.xml"/>
<root level="INFO">
<appender-ref ref="ASYNC_APPLICATION_LOG_FILE"/>
</root>
</springProfile>
</configuration>
・logback-file-appender.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<included>
<!-- LOG_PATH は Spring Boot が設定している logging.path から取得される。-->
<property name="APP_LOG_FILENAME" value="${LOG_PATH}/aplname.log"/>
<appender name="APPLICATION_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${APP_LOG_FILENAME}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${APP_LOG_FILENAME}.%d{yyyyMMdd}.gz</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}</pattern>
</encoder>
</appender>
<appender name="ASYNC_APPLICATION_LOG_FILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="APPLICATION_LOG_FILE"/>
</appender>
</included>
ログレベルは、できるだけ設定ファイル側(application.yml)に記述し、XML 側には書かない方がよいと思います。
Logback実行サンプル
それでは早速実装してみましょう。
開発時はログの出力はコンソールにし、テスト・本番ではファイルに出力されるように設定します。
・pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jp.demos.sblog</groupId>
<artifactId>spring-boot-logback</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
・Application.java
package jp.demos.sblog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application implements CommandLineRunner {
private final static Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@Override
public void run(String... args) throws Exception {
logger.info("ログレベル [INFO] で出力されるログ");
logger.debug("ログレベル [DEBUG] で出力されるログ");
}
}
・config/application.yml
spring:
profiles:
active: dev
・config/application-dev.yml
spring:
profiles: dev
logging:
level:
root: WARN
org:
springframework:
web: DEBUG
hibernate: ERROR
jp.demos.sblog: DEBUG
・config/application-test.yml
spring:
profiles: test
logging:
file: logs/logback-demo.log
level:
root: WARN
org:
springframework:
web: INFO
hibernate: ERROR
jp.demos.sblog: INFO
・config/application-production.yml
spring:
profiles: production
logging:
file: logs/logback-demo.log
level:
root: WARN
org:
springframework:
web: INFO
hibernate: ERROR
jp.demos.sblog: INFO
src/main/resources 配下に XML を2つ追加します。
・logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<!-- Spring Bootデフォルト設定読込 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<!-- 開発環境では、INFO レベル以上を console に出力する -->
<springProfile name="dev">
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<!-- テスト・本番環境では、INFO レベル以上を ファイル に出力する -->
<springProfile name="test, production">
<include resource="logback-file-appender.xml"/>
<root level="INFO">
<appender-ref ref="ASYNC_APPLICATION_LOG_FILE"/>
</root>
</springProfile>
</configuration>
・logback-file-appender.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<included>
<!-- LOG_FILE は Spring Boot が設定している logging.path から取得される。-->
<property name="APP_LOG_FILENAME" value="${LOG_FILE}"/>
<appender name="APPLICATION_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${APP_LOG_FILENAME}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${APP_LOG_FILENAME}.%d{yyyyMMdd}.gz</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}</pattern>
</encoder>
</appender>
<appender name="ASYNC_APPLICATION_LOG_FILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="APPLICATION_LOG_FILE"/>
</appender>
</included>
出来上がりはこんな感じになります。
動作検証
Application を動かしてみましょう。
・spring.profiles.active: dev の場合
コンソールにログが表示され、ログレベルが [DEBUG] であることが確認できます。
・spring.profiles.active: test の場合
カレントに logs/logback-demo.log が表示されます。
中身を見ると、ログレベルが [INFO] であることが確認できます。
翌日になれば出力ログは切り替わり、日別に管理されていることが確認できます。
ふむふむ、いい感じですね^^
まとめ
Spring BootでLogbackを使って日別にログ出力する方法を紹介しました。
ログ管理は、開発時はもちろん、運用開始してからは更に重要なものになります。開発時は発生しているエラーから、自前ロジックの問題なのか、フレームワークの設定や使い方に問題があるのか、などを判断する材料になります。運用開始後はシステムを止めるわけにはいきませんから、日次ログ監視に役立ち、トラブル発生時には前後のログを見て対応を考えます。アクセスログなどはユーザーの行動を知る大事な情報ですね。
以前、他社から運用を引き継いだシステムがありましたが、そのシステムでは一切ログ管理がされておらず、トラブル発生時の原因究明に苦慮した経験があります。いったいどうやって運用するつもりだったのか・・・開発時から誰も指摘しなかったのか・・・などなど、疑問だらけでしたけど、この時にログ管理の大切さを学びました。
トラブル発生時の原因究明と対策のために、システム利用者のために、なんといっても自分たちの作業負担軽減のためにも、きちんとしたログ管理をしていきたいですね。
おつかれさまでした。