配置logback以遵循Java配置,即简单的Java Logback配置

时间:2014-03-11 20:03:19

标签: java logging slf4j logback log4j2

我只是不喜欢Logback的XML或Groovy配置,并且更喜欢用Java进行配置(这也是因为我将在初始化后的不同时间在运行时更改配置)。

似乎进行Logback的Java配置的唯一方法是进行某种初始化hijacks the root appender或具有自定义系统属性,告诉logback不使用默认配置(这对单元测试来说相当烦人)和部署)。

我更喜欢的是logback.xml

<configuration javaConfig="com.myco.LogBackConfig" /> 

其中LogbackConfig有一些已建立的静态方法可以进行logback调用,或者它只是重新实例化一个Java bean。

这就是我想要一个默认的类路径资源,它会告诉logback使用Java而不是groovy / xml。基本上我想要一些类似于Java ServiceLoader的logback配置。

也许有一种方法可以在Logback中做到这一点,我错过了?

更新 显然是Log4j2 (the new log4j) does exactly what I want,与Java ServiceLoader非常相似。

3 个答案:

答案 0 :(得分:3)

此功能刚刚合并到logback的源代码中。见https://github.com/qos-ch/logback/pull/181

答案 1 :(得分:2)

这是一个绝对的黑客,但我认为它适用于你的情况:

在logback.xml文件中,将扫描设置为较短的时间间隔:http://logback.qos.ch/manual/configuration.html#autoScan

然后让您的代码修改后备文件,设置适当的级别。

Logback将重新扫描xml文件并应用更改。

答案 2 :(得分:1)

另一种方式。

logback version:1.1.2

<强> logback.xml

<configuration debug="true">
    <contextListener class="com.example.log.CustomLoggerContextListener"/>
</configuration>

<强> CustomLoggerContextListener.java

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.spi.LifeCycle;

public class CustomLoggerContextListener extends ContextAwareBase implements LoggerContextListener, LifeCycle {

    private boolean started = false;

    @Override
    public void start() {
        if (started) return;

        LoggerContext lctx = (LoggerContext) getContext();

        LoggerConfigurer configurer = new LoggerConfigurer();
        configurer.configure(lctx);

        started = true;
    }

    @Override
    public void stop() {
    }

    @Override
    public boolean isStarted() {
        return started;
    }

    @Override
    public boolean isResetResistant() {
        return true;
    }

    @Override
    public void onStart(LoggerContext context) {
    }

    @Override
    public void onReset(LoggerContext context) {
    }

    @Override
    public void onStop(LoggerContext context) {
    }

    @Override
    public void onLevelChange(Logger logger, Level level) {
    }
}

<强> LoggerConfigurer.java

import ch.qos.logback.classic.AsyncAppender;
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.filter.ThresholdFilter;
import ch.qos.logback.classic.html.HTMLLayout;
import ch.qos.logback.classic.net.SMTPAppender;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import ch.qos.logback.core.spi.CyclicBufferTracker;
import ch.qos.logback.core.status.InfoStatus;
import ch.qos.logback.core.status.StatusManager;

import java.io.File;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

public class LoggerConfigurer {

    public void configure(LoggerContext loggerContext) {
        loggerContext.reset();

        StatusManager sm = loggerContext.getStatusManager();

        if (sm != null) {
            sm.add(new InfoStatus("Setting configuration from " + getClass().getName(), loggerContext));
        }

        /**
         * Root Level
         */
        Logger rootLogger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);

        rootLogger.setLevel(Level.INFO);


        /**
         * Custom Log Levels
         */
        loggerContext.getLogger("com.example.package1").setLevel(Level.INFO);
        loggerContext.getLogger("com.example.package2").setLevel(Level.DEBUG);


        /**
         * Console Appender
         */
        configureConsoleAppender(loggerContext, rootLogger);

        /**
         * File Appender
         */
        configureFileAppender(loggerContext, rootLogger);

        /**
         * SMTP Mail Appender
         */
        configureMailAppender(loggerContext, rootLogger);
    }

    protected void configureConsoleAppender(LoggerContext loggerContext, Logger rootLogger) {
        ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<ILoggingEvent>();
        consoleAppender.setContext(loggerContext);
        consoleAppender.setName("myapp-log-console");
        consoleAppender.setEncoder(getEncoder(loggerContext));
        consoleAppender.start();

        rootLogger.addAppender(consoleAppender);
    }

    protected void configureFileAppender(LoggerContext loggerContext, Logger rootLogger) {
        String logFileName = "MY_LOG_FILE";
        String maxFileSize = "500mb";
        String logPath = "~/myAppLogs";
        int maxHistory = 7;
        String fileLogLevel = "WARN"; // if needed

        logPath = parseLogPath(logPath);
        logFileName = parseLogFileName(logFileName);

        RollingFileAppender<ILoggingEvent> rollingFileAppender = new RollingFileAppender<ILoggingEvent>();
        rollingFileAppender.setContext(loggerContext);
        rollingFileAppender.setName("log-file");
        rollingFileAppender.setFile(logPath + File.separator + logFileName + ".log");
        rollingFileAppender.setEncoder(getEncoder(loggerContext));
        rollingFileAppender.setAppend(true);

        TimeBasedRollingPolicy rollingPolicy = new TimeBasedRollingPolicy();
        rollingPolicy.setContext(loggerContext);
        rollingPolicy.setParent(rollingFileAppender);
        rollingPolicy.setFileNamePattern(logFileName + "-%d{yyyy-MM-dd}.log");
        rollingPolicy.setMaxHistory(maxHistory);
        rollingPolicy.start();

        SizeBasedTriggeringPolicy<ILoggingEvent> triggeringPolicy = new SizeBasedTriggeringPolicy<ILoggingEvent>();
        triggeringPolicy.setContext(loggerContext);
        triggeringPolicy.setMaxFileSize(maxFileSize);
        triggeringPolicy.start();

        rollingFileAppender.setRollingPolicy(rollingPolicy);
        rollingFileAppender.setTriggeringPolicy(triggeringPolicy);

        ThresholdFilter fileThresholdFilter = new ThresholdFilter();
        fileThresholdFilter.setName("file-thresholdFilter");
        fileThresholdFilter.setLevel(fileLogLevel);
        fileThresholdFilter.start();

        rollingFileAppender.start();

        AsyncAppender fileAsyncAppender = new AsyncAppender();
        fileAsyncAppender.setContext(loggerContext);
        fileAsyncAppender.setName(rollingFileAppender.getName() + "-async");
        fileAsyncAppender.addAppender(rollingFileAppender);
        fileAsyncAppender.setDiscardingThreshold(0);
        fileAsyncAppender.start();

        rootLogger.addAppender(fileAsyncAppender);
    }

    protected void configureMailAppender(LoggerContext loggerContext, Logger rootLogger) {
        List<String> toMails = Arrays.asList("mail1@mail.com", "mail2@mail.com");
        String host = "mail.host";
        Integer port = 22;
        String username = "mail.user";
        String password = "mail.password";
        String from = "mail.from";
        String subject = "mail.subject";
        Boolean startTLS = true;
        String mailLogLevel = "ERROR"; // if needed

        HTMLLayout htmlLayout = new HTMLLayout();
        htmlLayout.setContext(loggerContext);
        htmlLayout.setTitle(subject);
        htmlLayout.start();

        SMTPAppender smtpAppender = new SMTPAppender();
        smtpAppender.setContext(loggerContext);
        smtpAppender.setName("log-mail");
        smtpAppender.setSMTPHost(host);
        smtpAppender.setSMTPPort(port);
        smtpAppender.setUsername(username);
        smtpAppender.setPassword(password);
        smtpAppender.setFrom(from);
        smtpAppender.setSTARTTLS(startTLS);
        smtpAppender.setSubject(subject);
        smtpAppender.setLayout(htmlLayout);

        CyclicBufferTracker<ILoggingEvent> cyclicBufferTracker = new CyclicBufferTracker<ILoggingEvent>();
        cyclicBufferTracker.setBufferSize(1);
        smtpAppender.setCyclicBufferTracker(cyclicBufferTracker);


        ThresholdFilter mailThresholdFilter = new ThresholdFilter();
        mailThresholdFilter.setName("mail-thresholdFilter");
        mailThresholdFilter.setLevel(mailLogLevel);
        mailThresholdFilter.start();

        smtpAppender.addFilter(mailThresholdFilter);

        /**
         * to mail addresses
         */
        for (String toMail : toMails) {
            smtpAppender.addTo(toMail);
        }

        smtpAppender.start();

        AsyncAppender mailAsyncAppender = new AsyncAppender();
        mailAsyncAppender.setContext(loggerContext);
        mailAsyncAppender.setName(smtpAppender.getName() + "-async");
        mailAsyncAppender.addAppender(smtpAppender);
        mailAsyncAppender.setDiscardingThreshold(0);
        mailAsyncAppender.start();

        rootLogger.addAppender(mailAsyncAppender);
    }

    private PatternLayoutEncoder getEncoder(LoggerContext loggerContext) {
        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setContext(loggerContext);
        encoder.setPattern("%d{HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n");
        encoder.setCharset(Charset.forName("UTF-8"));
        encoder.start();
        return encoder;
    }

    private String parseLogFileName(String logFileName) {
        if (logFileName.startsWith("/") || logFileName.startsWith("\\")) {
            logFileName = logFileName.substring(1);
        }
        return logFileName;
    }

    private String parseLogPath(String logPath) {
        if (logPath.startsWith("~")) {
            logPath = logPath.replaceFirst("~", System.getProperty("user.home"));

        }
        if (logPath.endsWith("/") || logPath.endsWith("\\")) {
            logPath = logPath.substring(0, logPath.length() - 1);
        }
        return logPath;
    }
}