Logback.xml is not generating the logs separately for error and debug in separate rollingfile - logback

I want to generate logs in separate file for different level like error or debug. Means when root level is enable for Debug the logs should be generated in debug file only. And when root level is enable for error the logs should be generated in error file. But for my logback.xml configuration the logs are generating in both the files as the same time.
Please help.
=========Below is the logback.xml========
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="DEV_HOME" value="logs" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%-5level | %d{yyyy-MM-dd HH:mm:ss,SSS} [%thread] %logger{36} - %msg%n
</Pattern>
</layout>
<!-- filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>FATAL</level>
<onMatch>DENY</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>DENY</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter-->
</appender>
<appender name="Recipe_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${DEV_HOME}/Recipe_DEBUG.log</file>
<filter class="ch.qos.logback.core.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%-5level | %d{yyyy-MM-dd HH:mm:ss,SSS} [%thread] %logger{36} - %msg%n
</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${DEV_HOME}/archived/Recipe_DEBUG.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<appender name="Recipe_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${DEV_HOME}/Recipe_ERROR.log</file>
<filter class="ch.qos.logback.core.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%-5level | %d{yyyy-MM-dd HH:mm:ss,SSS} [%thread] %logger{36} - %msg%n
</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${DEV_HOME}/archived/Recipe_ERROR.%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<root level="ERROR">
<appender-ref ref="Recipe_ERROR" level="ERROR" additivity="true"/>
<appender-ref ref="Recipe_DEBUG" level="DEBUG" additivity="true"/>
</root>
</configuration>

There were some issues in filter and root tag, correcting and attaching the corrected file.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="DEV_HOME" value="logs" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%-5level | %d{yyyy-MM-dd HH:mm:ss,SSS} [%thread] %logger{36} - %msg%n
</Pattern>
</layout>
<!-- filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>FATAL</level>
<onMatch>DENY</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>DENY</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter-->
</appender>
<appender name="Recipe_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${DEV_HOME}/Recipe_DEBUG.log</file>
<append>true</append>
<!--filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%-5level | %d{yyyy-MM-dd HH:mm:ss,SSS} [%thread] %logger{36} - %msg%n
</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${DEV_HOME}/archived/Recipe_DEBUG.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<appender name="Recipe_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${DEV_HOME}/Recipe_ERROR.log</file>
<!--filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%-5level | %d{yyyy-MM-dd HH:mm:ss,SSS} [%thread] %logger{36} - %msg%n
</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${DEV_HOME}/archived/Recipe_ERROR.%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<!--additivity=false ensures this log data only goes to the this log, and no one more -->
<logger name="root" level="ERROR" additivity="false">
<appender-ref ref="Recipe_ERROR" />
<appender-ref ref="Recipe_DEBUG"/>
</logger>
</configuration>

Related

How to use JSON appender in Logback?

I am trying to output all my log events in JSON format.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<!--<appender-ref ref="kafkaAppender" />-->
<appender-ref ref="STDOUT" />
</root>
Maven Dependency:
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>4.7</version>
</dependency>
I see an error while running this configuration. Did i miss anything?
here is the stacktrace:
Exception in thread "main" java.lang.AbstractMethodError: net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder.headerBytes()[B
at ch.qos.logback.core.OutputStreamAppender.encoderInit(OutputStreamAppender.java:180)
at ch.qos.logback.core.OutputStreamAppender.setOutputStream(OutputStreamAppender.java:171)
at ch.qos.logback.core.ConsoleAppender.start(ConsoleAppender.java:81)
at ch.qos.logback.core.joran.action.AppenderAction.end(AppenderAction.java:90)
at ch.qos.logback.core.joran.spi.Interpreter.callEndAction(Interpreter.java:309)
at ch.qos.logback.core.joran.spi.Interpreter.endElement(Interpreter.java:193)
at ch.qos.logback.core.joran.spi.Interpreter.endElement(Interpreter.java:179)
at ch.qos.logback.core.joran.spi.EventPlayer.play(EventPlayer.java:62)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:165)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:152)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:110)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:53)
at ch.qos.logback.classic.util.ContextInitializer.configureByResource(ContextInitializer.java:75)
at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:150)
at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)
at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:55)
at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:273)
I had encountered the same error while using 4.7 version of the logstash-logback-encoder, and upgrading to 4.11 resolved the issue.
Ref- https://github.com/thumbtack/becquerel/issues/2

Backlog multi appender with different level

How can I log everything to WARN to a file and the console, but my.package to DEBUG only for file?
I tried:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern>
</encoder>
<File>target/log/test-log</File>
<append>false</append>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern>
</encoder>
</appender>
<logger name="my.package" level="WARN">
<appender-ref ref="STDOUT"/>
</logger>
<logger name="my.package" level="DEBUG">
<appender-ref ref="FILE" />
</logger>
<root level="WARN">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>
But it would log everything to DEBUG in the console too.
This also doesn't work:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern>
</encoder>
<File>target/log/test-log</File>
<append>false</append>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern>
</encoder>
</appender>
<logger name="io.chumps">
<appender-ref ref="STDOUT" level="WARN"/>
<appender-ref ref="FILE" level="DEBUG" />
</logger>
<root>
<appender-ref ref="STDOUT" level="WARN" />
<appender-ref ref="FILE" level="WARN" />
</root>
</configuration>
Solved it using GEventEvaluator with custom Groovy scripting:
http://logback.qos.ch/manual/filters.html#GEventEvaluator
<configuration>
<property name="LAYOUT" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n" />
<root>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.GEventEvaluator">
<expression>e.level.toInt() >= WARN.toInt()</expression>
</evaluator>
<OnMatch>ACCEPT</OnMatch>
<OnMismatch>DENY</OnMismatch>
</filter>
<encoder>
<pattern>${LAYOUT}</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.GEventEvaluator">
<expression>
e.level.toInt() >= WARN.toInt() ||
(e.level.toInt() >= TRACE.toInt() && e.getLoggerName().startsWith("my.package"))
</expression>
</evaluator>
<OnMatch>ACCEPT</OnMatch>
<OnMismatch>DENY</OnMismatch>
</filter>
<encoder>
<pattern>${LAYOUT}</pattern>
</encoder>
<File>target/log/test-log</File>
<append>false</append>
</appender>
</root>
</configuration>
I can't believe this so simple usecase is not supported by default.

How to switch defined appenders in logback

I have a defined logback in my project, and here is the configuration:
<?xml version="1.0" encoding="UTF-8"?>
<appender name="DAILY" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/logApp/application.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/logApp/application.log.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}:%line - %msg%n</pattern>
</encoder>
</appender>
<appender name="HOURLY" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/logApp/application.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/logApp/application.log.%d{yyyy-MM-dd-HH}.%i.gz</fileNamePattern>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}:%line - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="DAILY" />
</root>
A you can see I only use daily appender in my root configuration. How can I switch between those defined appenders (HOURLY / DAILY) in runtime?
I have tried with the following code, but my newAppender is always null:
String loggingAppender = "HOURLY";
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
ch.qos.logback.classic.Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME);
root.detachAndStopAllAppenders();
Appender<ILoggingEvent> newAppender = root.getAppender(loggingAppender);
root.addAppender(newAppender);

logback ThresholdFilter how todo the opposite

I need a filter that only passes through everything info and LESS instead of info and more. I have seen this done somewhere before in logback. My full xml is here and I want info and less to go to stdout (without writing a filter as I know that was possible somehow)...
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%date{ISO8601} %X{sessionid}-%X{user} %caller{1} %-4level: %message%n</pattern>
</layout>
</appender>
<appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>warn</level>
</filter>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%date{ISO8601} %X{sessionid}-%X{user} %caller{1} %-4level: %message%n</pattern>
</layout>
<target>System.err</target>
</appender>
figured it out finally....
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="30 seconds">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.GEventEvaluator">
<expression>
e.level.toInt() <= INFO.toInt()
</expression>
</evaluator>
<OnMismatch>DENY</OnMismatch>
<OnMatch>NEUTRAL</OnMatch>
</filter>
<encoder>
<pattern>%date{ISO8601} %X{sessionid}-%X{user} %caller{1} %-4level: %message%n</pattern>
</encoder>
</appender>
<appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>warn</level>
</filter>
<encoder>
<pattern>%date{ISO8601} %X{sessionid}-%X{user} %caller{1} %-4level: %message%n</pattern>
</encoder>
<target>System.err</target>
</appender>
<appender name="TEMP" class="com.alvazan.play.logging.CassandraAppender">
<appender-ref ref="STDOUT"/>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="STDOUT"/>
<appender-ref ref="STDERR"/>
<!-- appender-ref ref="TEMP"/-->
</root>
</configuration>

Logging into the file in Mule ESB

Can logging be done into the file in MULE ESB?.If so,please give me some examples and code snippets.Thanks in advance
Narayanan
You need to put log4j properties in your mule project inside main/resources directory. Here's sample log4j.xml that I am using with mule esb.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss} %-5p [%t] [%c] - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="ERROR" />
<param name="LevelMax" value="FATAL" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
<appender name="file" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="${mule.home}/logs/test.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
<param name="Append" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss} %-5p [%t] [%c] - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="INFO" />
<param name="LevelMax" value="FATAL" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
<root>
<priority value="DEBUG" />
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
</log4j:configuration>
Use the below log4j.xml file. Name the files as log4j.xml place it in the mule project classpath so that mule will pick this file when starting the app.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
</layout>
</appender>
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="c:/logs/gid/gid.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="FILE" />
</root>
</log4j:configuration>
Hope this helps you.
Thanks...
Yes we can save the entire logs in a file in any location. For that change the target(give the path where you want) in te log4j.xml file.
Since Mule 3.6 they changed the Log System from Log4j to Log4j2. Use the following content for your log4j2.xml file. Has been tested with Mule 3.8.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%-5p %d [%t] %c: %m%n"/>
</Console>
</Appenders>
<Loggers>
<!-- CXF is used heavily by Mule for web services -->
<AsyncLogger name="org.apache.cxf" level="WARN"/>
<!-- Apache Commons tend to make a lot of noise which can clutter the log-->
<AsyncLogger name="org.apache" level="WARN"/>
<!-- Reduce startup noise -->
<AsyncLogger name="org.springframework.beans.factory" level="WARN"/>
<!-- Mule classes -->
<AsyncLogger name="org.mule" level="INFO"/>
<AsyncLogger name="com.mulesoft" level="INFO"/>
<AsyncRoot level="INFO">
<AppenderRef ref="Console"/>
</AsyncRoot>
</Loggers>
</Configuration>