I am using logback/slf4j to do my logging. I want to parse my log file to analyze some data, so instead of parsing a great big file (mostly consisting of debug statements) I want to have two logger instances which each log to a separate file; one for analytics and one for all purpose logging. Does anyone know if this is possible with Logback, or any other logger for that matter?
Asked
Active
Viewed 1.2e+01k times
3 Answers
334
It's very possible to do something like this in logback. Here's an example configuration:
<?xml version="1.0"?>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>logfile.log</file>
<append>true</append>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
<appender name="ANALYTICS-FILE" class="ch.qos.logback.core.FileAppender">
<file>analytics.log</file>
<append>true</append>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
<!-- additivity=false ensures analytics data only goes to the analytics log -->
<logger name="analytics" level="DEBUG" additivity="false">
<appender-ref ref="ANALYTICS-FILE"/>
</logger>
<root>
<appender-ref ref="FILE"/>
</root>
</configuration>
Then you'd setup two separate loggers, one for everything and one to log analytics data like so:
Logger analytics = LoggerFactory.getLogger("analytics");
-
1I need to do this kind of thing so that i can have a no-line-feed appender and a regular appender to the same file. Thanks for this info. – djangofan Jan 16 '13 at 17:31
-
IMO additivity=false should be default if different appender-ref is specified. Very frequently we get application in which some modules will be very frequent log generators due to some timer events, and we would like to separate those logs into different files. Logging same log in 10 different files really does not make sense. So it should be an opt in feature not default. Since logback was a rewrite the same mistake should have been corrected by the same author. – samarjit samanta Mar 23 '15 at 07:39
-
I want to log error,debug,info messages in different files respectively . Is it possible with logback.xml – Qasim Jun 07 '15 at 14:20
-
@Qasim - that's possible. See - https://amitstechblog.wordpress.com/2014/09/27/logging-different-log-levels-to-different-appenders-with-logback/ – Andy Dufresne Jul 03 '15 at 10:15
-
I am trying to log logs from different packages to different files like this answer suggest but that doesn't work for me. My logback xml extract is here - http://pastebin.com/Aii4f1Jk. I am trying to log hibernate package TRACE level logs to a different file. Any suggestions? – Andy Dufresne Jul 03 '15 at 10:16
-
analytics never prints package name instead it prints analytics.method name. how to print the package name even after using string as a logger name – Prasad Oct 08 '17 at 06:16
-
@user1001 This is exactly why I used a programmatic approach inspired by this answer: https://stackoverflow.com/a/21280332/3676220 You just have to change the pattern layout to use the Class.getName() function instead of the %logger conversion word. Logback has no actual way of pairing a message to an appender, by choosing which appenders to use for each message for example. There is also the %caller conversion word in patternLayout, but since %line is stated to be slow and this contains line information, I can't imagine it being much faster. – Nick Zafiridis Feb 09 '20 at 20:08
11
You can have as many loggers as you wish. But, it's better you have one for each package that you need to log differently. Then all the classes in that package and its sub-packages will get the that specific logger. They all can share the root logger and send their log data to root logger appender using additivity="true". Here's an example:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="pattern" value="%date{HH:mm:ss.SSS} %-5p %logger{36}
%X{akkaSource} [%file:%line] - %m%n" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{HH:mm:ss.SSS} %-5p %logger{36} %X{akkaSource} [%file:%line] - %m%n</pattern>
</encoder>
</appender>
<appender name="abc" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${catalina.base}/logs/worker.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${catalina.base}/logs/worker-%d{yyyy-MM-dd_HH}.log</fileNamePattern>
<maxHistory>360</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<appender name="xyz" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${catalina.base}/logs/transformer.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${catalina.base}/logs/transformer-%d{yyyy-MM-dd_HH}.log</fileNamePattern>
<maxHistory>360</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<logger name="com.xxx.yyy.zzz" level="INFO" additivity="true">
<appender-ref ref="xyz"/>
</logger>
<logger name="com.aaa.bbb.ccc" level="INFO" additivity="true">
<appender-ref ref="abc"/>
</logger>
<root>
<level value="INFO" />
<appender-ref ref="STDOUT" />
</root>
4
in my case I wanted to leave class names as log name
private static final Logger log = LoggerFactory.getLogger(ScheduledPost.class);
and as I had few such classes, so my logback.xml
<!--additivity=false ensures this log data only goes to the this log, and no one more -->
<logger name="xxx.xxx.xxx.ScheduledPost" level="DEBUG" additivity="false">
<appender-ref ref="ASYNC_SCHEDULE_LOG_FILE"/>
</logger>
<logger name="xxx.xxx.xxx.GcmPost" level="DEBUG" additivity="false">
<appender-ref ref="ASYNC_SCHEDULE_LOG_FILE"/>
</logger>
<logger name="xxx.xxx.xxx.PushUtils" level="DEBUG" additivity="false">
<appender-ref ref="ASYNC_SCHEDULE_LOG_FILE"/>
</logger>