Log4j2 の設定を YAML で書く, Spring Boot でも使ってみる

設定ファイル関係を書くなら、
個人的には properties や XML や JSON より YAML が好きです。
ここでは Log4j2 の設定ファイルを YAML で書いてみました。

依存関係

設定ファイルを XML で書く場合は

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.2</version>
</dependency>

があれば大丈夫だけど、 YAML の場合は

<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-yaml</artifactId>
  <version>2.5.1</version>
</dependency>

も追加で必要のようです。
これがないと log4j2.yml を配置しても使ってくれませんでした。

設定ファイル

log4j2.xml

例えばこんな XML の場合。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
  <Appenders>
    <Console name="console">
      <PatternLayout pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} %-5level - %m%n" />
    </Console>
    <RollingFile name="file"
        fileName="${basedir}/logs/${project.build.finalName}.log"
        filePattern="${basedir}/logs/%d{yyyy-MM-dd}_${project.build.finalName}.log.gz">
      <PatternLayout pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} %-5level - %m%n" />
      <Policies>
        <TimeBasedTriggeringPolicy />
      </Policies>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Logger name="trylog4j2yaml" level="debug" additivity="false">
      <AppenderRef ref="console" />
      <AppenderRef ref="file" />
    </Logger>
    <Root level="warn">
      <AppenderRef ref="console" />
      <AppenderRef ref="file" />
    </Root>
  </Loggers>
</Configuration>

log4j2.yml

YAML だとこう書けました。
log4j2.xml の代わりに log4j2.yml を置けば OK。

AppenderRef のように同じ名前の要素が複数登場する場合は、
ハッシュの配列として要素名にぶらさげてやるといけました。

Configuration:
  status: "warn"
  Appenders:
    Console:
      name: "console"
      PatternLayout:
        pattern: "%d{yyyy/MM/dd HH:mm:ss.SSS} %-5level - %m%n"
    RollingFile:
      name: "file"
      fileName: "${basedir}/logs/${project.build.finalName}.log"
      filePattern: "${basedir}/logs/%d{yyyy-MM-dd}_${project.build.finalName}.log.gz"
      PatternLayout:
        pattern: "%d{yyyy/MM/dd HH:mm:ss.SSS} %-5level - %m%n"
      Policies:
        TimeBasedTriggeringPolicy: {}
  Loggers:
    Logger:
      - name: "trylog4j2yaml"
        level: "debug"
        additivity: "false"
        AppenderRef:
          - ref: "console"
          - ref: "file"
    Root:
      level: "warn"
      AppenderRef:
        - ref: "console"
        - ref: "file"

(ただ、これがベストな書き方かは分かってないです…)

Spring Boot 1.2.2 以上の場合

Spring Boot (spring-boot-starter-web) はデフォルトのログ出力実装が
Logback なので、まずはそれを Log4j に切り替えます。

spring-boot-starter-logging を外して
代わりに spring-boot-starter-log4j2 を追加すればOK。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <exclusions>
    <exclusion>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

あとは同様に、

  • 依存関係に jackson-dataformat-yaml を追加。
  • log4j2.xml の代わりに log4j2.yml を配置。

をやればいけました。

Spring Boot 1.2.1 以下の場合

log4j2.yml を置いても無視されました…
Spring Boot の自動設定で読みに行くファイル名のリストに
log4j2.yml が入ってないようでした。

だったら自分で指定しちゃえとゆーことで、application.yml
log4j2.yml のファイルパスを指定すると使えました。

# application.yml
logging:
  config: "classpath:log4j2.yml"

多分こちらの Issue に該当。
1.2.2 で修正されたようです。

Support log4j2 with yaml format - Issue #2239 - spring-projects/spring-boot

サンプルコード