Andrey Hihlovskiy
Professional blog on groovy, gradle, Java, Javascript and other stuff.
Tag Archives: PatternLayoutEncoder
Programmatic configuration of slf4j/logback
July 11, 2013
Posted by on Now I have experience with programmatic configuration of slf4j/logback.
Task
A program must open separate log file for each processed input file.
Solution for task
Instead of configuring logback via xml, the one needs to “manually” instantiate encoders, appenders and loggers, then configure and link them together.
Caveat 1
Logback goes crazy on attempt to share encoder (i.e. PatternLayoutEncoder) between appenders.
Solution for caveat 1
Create separate encoder for each appender.
Caveat 2
Logback refuses to log anything, if encoders and appenders are not associated with logging context.
Solution for caveat 2
Call setContext on each encoder and appender, passing LoggerFactory as a parameter.
Caveat 3
Logback refuses to log anything, if encoders and appenders are not started.
Solution for caveat 3
encoders and appenders need to be started in the correct order, i.e. first encoders, then appenders.
Caveat 4
RollingPolicy objects (i.e. TimeBasedRollingPolicy) produce strange error messages like “date format not recognized”, when they are not attached to the same context as appender.
Solutin for caveat 4
call setContext on RollingPolicy same way as on encoders and appenders.
Here is working example of “manual” logback configuration:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testpackage | |
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.core.ConsoleAppender | |
import ch.qos.logback.core.rolling.RollingFileAppender | |
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy | |
import org.slf4j.LoggerFactory | |
class TestLogConfig { | |
public static void main(String[] args) { | |
LoggerContext logCtx = LoggerFactory.getILoggerFactory() | |
PatternLayoutEncoder logEncoder = new PatternLayoutEncoder() | |
logEncoder.setContext(logCtx) | |
logEncoder.setPattern('%-12date{YYYY-MM-dd HH:mm:ss.SSS} %-5level – %msg%n') | |
logEncoder.start() | |
ConsoleAppender logConsoleAppender = new ConsoleAppender() | |
logConsoleAppender.setContext(logCtx) | |
logConsoleAppender.setName('console') | |
logConsoleAppender.setEncoder(logEncoder) | |
logConsoleAppender.start() | |
logEncoder = new PatternLayoutEncoder() | |
logEncoder.setContext(logCtx) | |
logEncoder.setPattern('%-12date{YYYY-MM-dd HH:mm:ss.SSS} %-5level – %msg%n') | |
logEncoder.start() | |
RollingFileAppender logFileAppender = new RollingFileAppender() | |
logFileAppender.setContext(logCtx) | |
logFileAppender.setName('logFile') | |
logFileAppender.setEncoder(logEncoder) | |
logFileAppender.setAppend(true) | |
logFileAppender.setFile('logs/logfile.log') | |
TimeBasedRollingPolicy logFilePolicy = new TimeBasedRollingPolicy() | |
logFilePolicy.setContext(logCtx) | |
logFilePolicy.setParent(logFileAppender) | |
logFilePolicy.setFileNamePattern('logs/logfile-%d{yyyy-MM-dd_HH}.log') | |
logFilePolicy.setMaxHistory(7) | |
logFilePolicy.start() | |
logFileAppender.setRollingPolicy(logFilePolicy) | |
logFileAppender.start() | |
Logger log = logCtx.getLogger("Main") | |
log.additive = false | |
log.level = Level.INFO | |
log.addAppender(logConsoleAppender) | |
log.addAppender(logFileAppender) | |
} | |
} |
My conclusion: logback is much easier to configure via XML. “Manual” configuration is rather tedious task and should be avoided, unless it is dictated by project needs.
Recent Comments