Logbackで設定ファイルを切り替える


処理内容によってログ出力先を変えたりしたくなることがありますね。クラスのパッケージ名とかMarkerで指定する方法もありますが、設定ファイルをまるごと切り替えるやり方も割と便利です。

Invoking JoranConfigurator directlyで解説されている読み込むファイルを直接指定読み込む方法を使うと、以下のように動的にLogbackの設定を切り替えることができます。

package org.hogel;

import java.io.FileNotFoundException;
import java.net.URL;

import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;

public class LoggerConfigLoader {
    public static enum Mode {
        CONSOLE("logback-console"),
        FILE("logback-file");

        private final String[] resourceNames;
        private Mode(String resourceName) {
            resourceNames = new String[] {
                '/' + resourceName + "-test.xml",
                '/' + resourceName + ".xml",
            };
        }

        public URL getXmlResource() throws FileNotFoundException {
            for (String resourceName : resourceNames) {
                URL resource = LoggerConfigLoader.class.getResource(resourceName);
                if (resource != null) {
                    return resource;
                }
            }
            throw new FileNotFoundException("resource not found!");
        }
    }

    public static void setMode(Mode mode) throws FileNotFoundException, JoranException {
        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();

        context.reset();
        JoranConfigurator configurator = new JoranConfigurator();
        configurator.setContext(context);

        URL configUrl = mode.getXmlResource();
        configurator.doConfigure(configUrl);
    }
}

こんな感じで CONSOLE, FILE モードを切り替えて、設定ファイルを

  • logback-console.xml / logback-console-test.xml
  • logback-file.xml / logback-file-test.xml

から読み込むように。
使う側は単純にモードを設定するだけで出力先を切り分けられます。

package org.hogel;

import java.io.FileNotFoundException;

import org.hogel.LoggerConfigLoader.Mode;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.core.joran.spi.JoranException;

public class LoggerConfigLoaderTest {
    private static final Logger LOG = LoggerFactory.getLogger("test");

    @Test
    public void console() throws FileNotFoundException, JoranException {
        LoggerConfigLoader.setMode(Mode.CONSOLE);
        LOG.debug("console debug!"); // -> stdout
    }

    @Test
    public void file() throws FileNotFoundException, JoranException {
        LoggerConfigLoader.setMode(Mode.FILE);
        LOG.debug("file debug!"); // -> target/file.log
    }

    @Test
    public void mixed() throws FileNotFoundException, JoranException {
        LoggerConfigLoader.setMode(Mode.CONSOLE);
        LOG.debug("console debug!"); // -> stdout
        LoggerConfigLoader.setMode(Mode.FILE);
        LOG.debug("file debug!"); // -> target/file.log
    }
}

mixed() のテストにあるように途中で切り替えることもできます。

ただしSetting the context nameで説明されているように、 contextName の設定は初期状態の default からそれ以外の値への変更、最初の一回のみ有効です。例えばlogback-console.xmlとlogback-file.xml両方に contextName が設定されている場合に mixed() のように途中で設定を切り替えると contextName はlogback-console.xmlの記述のみが有効です。

ここで例に出したコード一式 https://github.com/hogelog/java-practice の logback-sample にあります。