Java
logger
log4j
spring-boot
slf4j

Java でロガーを SLF4J に統一する冴えたやり方 / build.gradle 記入法

SLF4J を使いたいこんな人向けの記事です


  • SLF4J に統一したはずなのに、たまにコンソールに謎ログが出てる。時刻が出ないとかある


  • Class path contains multiple SLF4J bindings. SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. なるログが出る


  • ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console... なるログができる

  • gradle/maven で exclude すると除外できるのは知ってるけど、新規ライブラリを追加したタイミングで log4j の実装が混入してログがでなくなったりしている

  • まとめて log4j や commons-logging を取り除きたい


Tips


除外について

以下の構文で一括 除外 ができる

configurations.all {

exclude
}


依存バージョンの統一

pring-gradle-plugins/dependency-management-plugin が便利


build.gradle

plugins {

id "io.spring.dependency-management" version "1.0.6.RELEASE"
}

dependencyManagement {
dependencies {
dependency 'ch.qos.logback:logback-classic:1.2.3'
dependency 'org.apache.logging.log4j:log4j-core:2.11.1'
dependency 'org.apache.logging.log4j:log4j-to-slf4j:2.11.1'
dependency 'org.slf4j:jcl-over-slf4j:1.7.25'
dependency 'org.slf4j:jul-to-slf4j:1.7.25'
dependency 'org.slf4j:slf4j-api:1.7.25'
}
}



複数の SLF4J jar があると怒られる Class path contains multiple SLF4J bindings. について

IntelliJ の Issue のようだけど、依存ライブラリで SLF4J を使っていて、runtime で別のバージョンのライブラリを導入した場合、IntelliJ 内から Debug/Run したときに両方の Jar が Classpath に含まれてしまう問題があるようだ。。

基本的に、dependencyManagement をしておけば大丈夫。


TL;DR


Pattern 1

全てのプロジェクトに 各種ログライブラリ > SLF4J で出力、に必要なモジュールを入れて、各種ログライブラリの実装のほうを Exclude してやればよい。


build.gradle

plugins {

id "io.spring.dependency-management" version "1.0.6.RELEASE"
}

repositories {
mavenCentral()
}

apply plugin: 'java'

dependencyManagement {
dependencies {
dependency 'ch.qos.logback:logback-classic:1.2.3'
dependency 'org.apache.logging.log4j:log4j-core:2.11.1'
dependency 'org.apache.logging.log4j:log4j-to-slf4j:2.11.1'
dependency 'org.slf4j:jcl-over-slf4j:1.7.25'
dependency 'org.slf4j:jul-to-slf4j:1.7.25'
dependency 'org.slf4j:slf4j-api:1.7.25'
}
}

dependencies {
// Used compile/coding time.
implementation 'org.slf4j:slf4j-api:1.7.25'

// Used Runtime
runtimeOnly 'ch.qos.logback:logback-classic' // The log implementation.
runtimeOnly 'org.slf4j:jcl-over-slf4j' // Commons-Logging > SLF4J
runtimeOnly 'org.slf4j:jul-to-slf4j' // Java Util Logging > SLF4J
runtimeOnly 'org.apache.logging.log4j:log4j-core' // Log4j 1&2 Core
runtimeOnly 'org.apache.logging.log4j:log4j-to-slf4j' // Log4j 1&2 > SLF4J
}

configurations.all {
exclude group: 'log4j' // = Log4j implementation.
exclude module: 'log4j-slf4j-impl' // = SLF4J > Log4J Implementation. (Apache Side)
exclude module: 'slf4j-log4j12' // = SLF4J > Log4J Implementation. (SLF4J Side)
exclude module: 'log4j-over-slf4j' // = Old Log4j 1&2 > SLF4J
exclude module: 'slf4j-jdk14' // = SLF4J > JDK14 Binding
exclude module: 'commons-logging' // Because bridged by jcl-over-slf4j
exclude module: 'commons-logging-api' // Replaced by jcl-over-slf4j
}



Pattern 2

ログの設定などを含めたログ専用プロジェクトを作ってしまうのもおすすめ

後で書く


build.gradle




log/build.gradle