Secret Staircase

logback の設定ファイルを環境ごとに動的に変更する

[logback の設定ファイル内で条件分岐]({% post_url 2013-04-15-logback-conditional-configuration %}) では設定ファイル内で環境ごとに分岐したけれど、差異が大きい場合はファイルをごっそり分けた方がよいでしょう。logback では ContextInitializer が設定ファイルの読み込みを行っています。これを設定ファイル名とともに明示的に呼ぶことで再設定できます。

ServletContextListener でシステムプロパティ app.env の値によって log-<app.env>.groovy を選択する例

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.joran.spi.JoranException;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.net.URL;

@WebListener
public class LogConfigListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        try {
            LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
            context.reset();
            new ContextInitializer(context).configureByResource(getConfigUrl());
        } catch (JoranException e) {
            throw new RuntimeException(e);
        }
    }

    private URL getConfigUrl() {
        return Thread.currentThread().getContextClassLoader().getResource(getConfigFilename());
    }

    private String getConfigFilename() {
        String env = System.getProperty("app.env");
        if (env == null) {
            return "log.groovy";
        } else {
            return "log-" + env + ".groovy";
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

なんか微妙に裏技感あるなあ...