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

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

[Invoking JoranConfigurator directly](http://logback.qos.ch/manual/configuration.html#joranDirectly)で解説されている読み込むファイルを直接指定読み込む方法を使うと、以下のように動的に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](http://logback.qos.ch/manual/configuration.html#contextName)で説明されているように、 _contextName_ の設定は初期状態の _default_ からそれ以外の値への変更、最初の一回のみ有効です。例えばlogback-console.xmlとlogback-file.xml両方に _contextName_ が設定されている場合に _mixed()_ のように途中で設定を切り替えると _contextName_ はlogback-console.xmlの記述のみが有効です。

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