LoginSignup
12
3

More than 5 years have passed since last update.

logbackでプログラマブルにLoggerを生成する

Last updated at Posted at 2017-12-04

この記事は リクルートライフスタイルアドベントカレンダー2017 の5日目です。
ホットペッパービューティーでゆるふわエンジニアをしています。しゃぜです。

logbackでプログラマブルにLoggerを生成すると題しまして、動的なLogger生成について書いてみます。
ま、あんまりドキュメントに無さそうな、logback小ネタです。

はじめに

通常logbackを使う際は、以下のようなlogback.xmlを用意すると思います。

logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>

    <appender name="APP"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/var/log/app.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
            <maxHistory>14</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>time:%d{yyyy-MMM-dd HH:mm:ss.SSS}  level:%level  marker:%marker thread:%thread  logger:%logger  file:%file  line:%line  message:%msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="APP" />
    </root>

</configuration>

やりたいこと

ところが、このXML記法だと困るケースがありました。具体的にいうと、この仕事の時だったんですが。

やりたかったこととしては、ログファイルのPATHを動的に設定したいです。どういうことかというと...。

  • 条件
    • host1から転送されてきたログは、/tmp/host1/app-yyyyMMdd.logとする。
    • hostNから転送されてきたログは、/tmp/hostN/app-yyyyMMdd.logとする。
    • hostは可変である。

というものです。まぁ、転送されてくるホストの増減に合わせて、xmlをメンテナンスするとかやりたくないです。

いろんなやり方があると思うのですが(logbackを使わないも含めて)、今回はlogbackでプログラマブルにLoggerの生成するやりかたでやってみました。

以下動作サンプルのコードです。githubにもあげておきますね。https://github.com/shase/logback-dynamic-logger-sample

Main.java
import java.util.stream.Stream;
import ch.qos.logback.classic.Logger;

public class Main {

    public static void main(String...args) {
        // ここは外部からhost名が入ってくるのをイメージしてみてください。
        String[] path = {"/tmp/host1/app-%d{yyyyMMdd}.log","/tmp/host2/app-%d{yyyyMMdd}.log","/tmp/host3/app-%d{yyyyMMdd}.log"};

        Stream.of(path)
            .forEach(p -> {
                Logger logger = new SimpleLoggerFactory().getLogger("sample", p);
                logger.info("dynamic path");
            });
    }

}
SimpleLoggerFactory.java
import java.nio.charset.StandardCharsets;

import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;

public class SimpleLoggerFactory {
    public Logger getLogger(String loggerName, String path) {

        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

        PatternLayoutEncoder ple = new PatternLayoutEncoder();
        ple.setPattern("%msg%n");
        ple.setContext(lc);
        ple.setCharset(StandardCharsets.UTF_8);
        ple.start();

        RollingFileAppender<ILoggingEvent> fileAppender = new RollingFileAppender<>();
        TimeBasedRollingPolicy<ILoggingEvent> rollingPolicy = new TimeBasedRollingPolicy<>();
        rollingPolicy.setFileNamePattern(path);
        rollingPolicy.setMaxHistory(14);
        rollingPolicy.setParent(fileAppender);
        rollingPolicy.setContext(lc);
        rollingPolicy.start();

        fileAppender.setAppend(true);
        fileAppender.setEncoder(ple);
        fileAppender.setRollingPolicy(rollingPolicy);
        fileAppender.setContext(lc);
        fileAppender.start();

        Logger logger = (Logger) LoggerFactory.getLogger(loggerName);
        logger.addAppender(fileAppender);
        logger.setAdditive(false);

        return logger;
    }
}
  • これによって、出力先のpathを動的にすることができました。
  • logbackを普段使っている人が見ればわかると思いますが、普段xmlで定義していることをそのまま書いているだけですね。
  • この例ではxmlは不要です。

おわりに

  • 実際に使う際は、毎回同じloggerを生成する必要はないので(初回生成だけでよいので)、何かしらの手段でsingletonにするとよいでしょう。
  • これを書いた後に気がついたのですが、logbackにはGroovy Configurationもあるので、そっちでもやりたいことはできたのかも?機会があったら試してみようと思います。
  • ではではー。Merry Xmas !!!
12
3
0

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
12
3