7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Spring Boot でロギングライブラリをLog4j2にする

Last updated at Posted at 2021-06-09

Spring Boot のロギングライブラリのデフォルトは Logback で、ファサードとして SLF4J が使われる。
これを log4j2 に切り替える場合の設定を残しておく

log4j2 のバージョンをカスタマイズする

12/11 追記: log4j2 の脆弱性の話があったので、log4j2 のバージョンをカスタマイズする方法を追記

build.gradle.kts
...
apply(plugin = "io.spring.dependency-management")
...
extra["log4j2.version"] = "2.15.0"
...
  • io.spring.dependency-management プラグインを適用して SpringBoot アプリケーションの依存関係を管理しておく(多分、大体追記されている??)
  • spring bootのバージョンがアップデートされて log4j2 のバージョンも上がったら、extra["log4j2.version"] = "2.15.0" は削除しないと逆に 2.15.0 に固定されてしまう
  • 上記は Kotlin DSL の場合。Groovy なら ext['log4j2.version'] = '2.15.0'

参考リンク
Spring Boot Gradle プラグインリファレンスガイド - 3.1.1. 管理バージョンのカスタマイズ
依存バージョン - 2.バージョンプロパティ
log4j2 のバージョンアップのやりかた

調査時のバージョン

gradle: 6.9
spring-boot-starter-web: 2.5.0
spring-boot-starter-log4j2: 2.5.0
spring-boot-starter-aop: 2.5.0
jdk: liberica 11.0.11

ロギングライブラリを Logback から log4j2 に切り替える

  1. spring-boot-starter-log4js を依存関係に含める
  2. spring-boot-starter-logging を依存関係から除外する
build.gradle.kts
...

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-log4j2")
    implementation("org.springframework.boot:spring-boot-starter-aop")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

configurations {
    all {
        exclude("org.springframework.boot", "spring-boot-starter-logging")
    }
}

...

LoggingException が 発生する場合

maven だと、spring-boot-starter-web に対して、spring-boot-starter-logging を除外(<exclusion>)するとあったので、gradle でもそれに従って記述したが、起動時にCaused by: org.apache.logging.log4j.LoggingException: log4j-slf4j-impl cannot be present with log4j-to-slf4jが発生してしまった。

stackoverflow にて「全てのライブラリから spring-boot-starter-logging を除外する必要がある」ことがわかったので、configuration.all で除外するように書き換えると log4j2 に切り替わった。

build.gradle.kts
// LogingExceptionが発生する書き方
implementation("org.springframework.boot:spring-boot-starter-web"){
    exclude("org.springframework.boot","spring-boot-starter-logging")
}

// このように全ての依存関係から、spring-boot-starter-logging を除外する必要がある
configurations {
    all {
        exclude("org.springframework.boot", "spring-boot-starter-logging")
    }
}

GradleならModule replacement が使える

exclude で除外しなくても dependenciesブロック内で次のように定義することで、spring-boot-starter-loggingを参照する場面で、spring-boot-starter-log4j2 に置き換えてくれる

build.gradle.kts
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-log4j2")
    modules {
        module("org.springframework.boot:spring-boot-starter-logging") {
            replacedBy("org.springframework.boot:spring-boot-starter-log4j2", "Use Log4j2 instead of Logback")
        }
    }
}

ロギングファサードもSLF4J から Log4j2 に切り替える

ここまでの設定だとログ出力をlogbackからlog4j2に変えただけであり、ロギングのファサードは slf4jのまま。つまり slf4j + log4j2 に切り替わったことになる。ロギングファサードもsl4jからlog4j2 に変えたい場合は、Logger クラスを変えれば良い


import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger

// LogManagerクラスからLoggerクラスを取得する
private val logger: Logger = LogManager.getLogger(LoggingAdvice::class.java)

// SLF4J を使う場合は、LoggerFactoryを使う
//private val logger = LoggerFactory.getLogger(LoggingAdvice::class.java)

@Aspect
@Component
class LoggingAdvice {

...

}

(2023.03.29補足)
ロギングファサードは SLF4J を使った方が ログ出力はlog4j2/logbackのどちらにも対応するので、無理にlog4j2に切り替えなくても良い気がするのが最近のお気持ち

log4j2 の設定ファイル (参考)

Spring における log4j2 のロギング設定は、 ./src/main/resources/log4j2-spring.xml に記述することでカスタマイズできる。

log4j2 の設定ファイルは YAML や JSON でも書けるが、Spring からは、XML 形式でないと参照しない模様。
また、ファイル名は log4j2-spring.xml と、'-spring' をつけないと起動時のロード順によって 設定ファイルから Springのプロパティが読み込めないので注意する。

4.8.カスタムログ設定」 より
可能な場合、ロギング構成に -spring バリアントを使用することをお勧めします(たとえば、logback.xml ではなく logback-spring.xml)。標準の構成場所を使用する場合、Spring はログの初期化を完全に制御できません。

以下は、設定例

log4j2-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight{%-5level}[%style{%t}{bright,blue}] %style{%C}{bright,yellow}: %m%n"/>
        </Console>
        <RollingFile name="RollingFile"
                     fileName="./logs/spring-boot-logger-log4j2.log"
                     filePattern="./logs/$${date:yyyy-MM}/spring-boot-log4j2-%d{-dd-MMMM-yyyy}-%i.log.gz">
            <PatternLayout>
                <pattern>%d %p %C [%t] %m%n</pattern>
            </PatternLayout>
            <Policies>
                <OnStartupTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="10 MB"/>
                <TimeBasedTriggeringPolicy/>
            </Policies>
        </RollingFile
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFile"/>
        </Root>
    </Loggers>
</configuration>

YAMLなど XML以外のフォーマットで読み込むためには 必要なDependencyを追加すれば良さそう(動作は未確認)

https://docs.spring.io/spring-boot/docs/3.0.3/reference/htmlsingle/#howto.logging.log4j.yaml-or-json-config

参考リンク

Spring Boot の機能 4.ログ
Log4j 2 - configuration
(Baeldung) Logging in Spring Boot
(stack overflow) Caused by: org.apache.logging.log4j.LoggingException: log4j-slf4j-impl cannot be present with log4j-to-slf4j

7
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?