Spring Bootで日別にログ出力する方法(Logback)

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 ファイルがデフォルトとなっています。

Spring Boot Logback 4XML

ファイル名説明
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>

出来上がりはこんな感じになります。

Spring Boot Logbackを使ったサンプル構成

動作検証

Application を動かしてみましょう。

・spring.profiles.active: dev の場合

コンソールにログが表示され、ログレベルが [DEBUG] であることが確認できます。

Spring Boot Logback ログレベルDEBUG

・spring.profiles.active: test の場合

カレントに logs/logback-demo.log が表示されます。

Spring Boot カレントにログが出力される

中身を見ると、ログレベルが [INFO] であることが確認できます。

Spring Boot Logback ログレベルINFO

翌日になれば出力ログは切り替わり、日別に管理されていることが確認できます。

Spring Boot 日別ログ管理

ふむふむ、いい感じですね^^

まとめ

Spring BootでLogbackを使って日別にログ出力する方法を紹介しました。

ログ管理は、開発時はもちろん、運用開始してからは更に重要なものになります。開発時は発生しているエラーから、自前ロジックの問題なのか、フレームワークの設定や使い方に問題があるのか、などを判断する材料になります。運用開始後はシステムを止めるわけにはいきませんから、日次ログ監視に役立ち、トラブル発生時には前後のログを見て対応を考えます。アクセスログなどはユーザーの行動を知る大事な情報ですね。

以前、他社から運用を引き継いだシステムがありましたが、そのシステムでは一切ログ管理がされておらず、トラブル発生時の原因究明に苦慮した経験があります。いったいどうやって運用するつもりだったのか・・・開発時から誰も指摘しなかったのか・・・などなど、疑問だらけでしたけど、この時にログ管理の大切さを学びました。

トラブル発生時の原因究明と対策のために、システム利用者のために、なんといっても自分たちの作業負担軽減のためにも、きちんとしたログ管理をしていきたいですね。

おつかれさまでした。

この記事がお役に立ちましたら シェア をお願いいたします。