kagamihogeの日記

kagamihogeの日記です。

SLF4J + Log4j 2さわる

SLF4J + Log4j 2のhello worldレベルのことをやる。

環境

やったこと

SLF4J

pom.xmlに依存性を追加する。

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.10</version>
</dependency>

SLF4J Manualのサンプルコードをコピペしてくる。

package com.example.slf4jlog4j2;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(App.class);
        logger.info("Hello World");
    }
}

実行すると、ロガー実装とのバインディング設定が無いので、デフォルトの何もしないロガー(no-operation (NOP) logger)実装を使用した、的なwarningが出力される。

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

これを一先ず無くすにはSLF4J Simple Bindingを使え、とマニュアルにあるので使ってみる。

SLF4J + SLF4J Simple Binding

pom.xmlに依存性を追加する。

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.10</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.10</version>
</dependency>

実行する。

[main] INFO com.example.slf4jlog4j2.App - Hello World

ログがコンソールに出力された。

SLF4J ManualのTypical usage patternにあるサンプルコードをコピペしてくる。動作を見るため、logger.debugとなっている箇所をlogger.infoに変更する。

package com.example.slf4jlog4j2;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Wombat {
    final Logger logger = LoggerFactory.getLogger( Wombat.class);

    Integer t;
    Integer oldT;

    public void setTemperature(Integer temperature) {
        oldT = t;
        t = temperature;

        logger.info("Temperature set to {}. Old temperature was {}.", t, oldT);

        if (temperature.intValue() > 50) {
            logger.info("Temperature has risen above 50 degrees.");
        }
    }

    public static void main(String[] args) {
        Wombat a = new Wombat();
        a.setTemperature(200);
        a.setTemperature(30);
    }

}

実行するとこんな感じ。プレースホルダが出力されているのが分かる。

[main] INFO com.example.slf4jlog4j2.Wombat - Temperature set to 200. Old temperature was null.
[main] INFO com.example.slf4jlog4j2.Wombat - Temperature has risen above 50 degrees.
[main] INFO com.example.slf4jlog4j2.Wombat - Temperature set to 30. Old temperature was 200.

SLF4J + Apache Log4j SLF4J Binding + Apache Log4j 2

ロガー実装のバインディングLog4j 2にする。

pom.xmlに依存性を追加する。上から、SLF4J本体、SLF4JとLog4J 2のバインディングを行うライブラリ、Log4j 2の本体。

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.10</version>
</dependency>

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.1</version>
</dependency>

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

Log4j 2の設定ファイルをテキトーに作る。src/main/resources/log4j2.xmlとかを下みたいな感じにする。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyy/MM/dd HH:mm:ss.SSS} %-5level - %msg%n" />
        </Console>
    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

これでさっきのサンプルコードを動かすとこんな感じになる。

2015/01/20 21:11:08.217 INFO  - Temperature set to 200. Old temperature was null.
2015/01/20 21:11:08.229 INFO  - Temperature has risen above 50 degrees.
2015/01/20 21:11:08.229 INFO  - Temperature set to 30. Old temperature was 200.

ハマったこと

No log4j2 configuration file found

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.

log4j 2の設定ファイル(log4j2.xmlとか)が無いか、パスが通ってない。

java.lang.NoSuchMethodError: org.apache.logging.log4j.spi.LoggerContext.getLogger

Exception in thread "main" java.lang.NoSuchMethodError: org.apache.logging.log4j.spi.LoggerContext.getLogger(Ljava/lang/String;)Lorg/apache/logging/log4j/Logger;

pom.xmlを↓みたいにしてしまうと、上記のエラーが出る。詳しいことは分からんけどorg.apache.logging.log4j.adaptersslf4j-implはエラーになる。2.0-beta2とかbetaがついてるし、Log4j 2のバインディングとして使うにはなんかダメなんでしょう。

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.10</version>
</dependency>

<!-- ここから 下記は間違い -->
<dependency>
    <groupId>org.apache.logging.log4j.adapters</groupId>
    <artifactId>slf4j-impl</artifactId>
    <version>2.0-beta2</version>
</dependency>
<!-- ここまで-->

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

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.1</version>
</dependency>