How to Configure Log4J to Log Different Log Levels to Different Files for the Same Logger

How to configure log4j to log different log levels to different files for the same logger

What you need to do is have a single <logger> definition with a defined level of INFO, but in your two appender definitions, you set their thresholds accordingly, e.g.

<appender name="ERROR_FILE">
<param name="Threshold" value="ERROR"/>
</appender>

<appender name="GENERAL">
<param name="Threshold" value="INFO"/>
</appender>

You then add both appenders to your logger:

<logger name="com.acme">
<level value="INFO"/>
<appender-ref ref="ERROR_FILE"/>
<appender-ref ref="GENERAL"/>
</logger>

Log entries now going to the logger will get sent to both appenders, but since they have different independent thresholds, the ERROR_FILE appender will only log ERROR and above.

Different level of logs in different log files

Finally got the answer by doing this i got the logs in different files.

<Loggers>
<logger name="com.mvc.login" level="info" additivity="false">
<AppenderRef ref="LoginController" level="error"/>
<AppenderRef ref="InfoController" level="info"/>
</logger>
</Loggers>

Logging different levels using same object to different files

You could use filters to deny any messages except those of the level you want. Here is an example of how to do this:

First a class to test our efforts:

package test;
import org.apache.log4j.Logger;

public class Main {

private static final Logger logger = Logger.getLogger(Main.class);
public static void main(String[] args) {
logger.debug("here's some debug");
logger.info("here's some info");
logger.warn("here's some warn");
logger.error("here's some error");
logger.fatal("here's some fatal");
}

}

Next a log4j.xml config file to set up the appenders and loggers:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c{1}] %m %n" />
</layout>
</appender>

<appender name="debugLog" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logs/debug.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="5000KB" />
<param name="maxBackupIndex" value="5" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p - %m%n" />
</layout>

<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="DEBUG" />
<param name="AcceptOnMatch" value="true" />
</filter>

<filter class="org.apache.log4j.varia.DenyAllFilter" />
</appender>

<appender name="infoLog" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logs/info.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="5000KB" />
<param name="maxBackupIndex" value="5" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p - %m%n" />
</layout>

<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="INFO" />
<param name="AcceptOnMatch" value="true" />
</filter>

<filter class="org.apache.log4j.varia.DenyAllFilter" />
</appender>

<logger name="test" additivity="false">
<level value="DEBUG" />
<appender-ref ref="consoleAppender" />
<appender-ref ref="debugLog" />
<appender-ref ref="infoLog" />
</logger>
</log4j:configuration>

This pattern will allow you to generate a separate log for each log level, just repeat the configuration that I have provided for either debug or info logging. Note that the console appender will accept all levels.

I was able to gain some insight from this post so I thought I should give credit.

log different log levels to different files with log4j

The standard behaviour for log4j appenders is that they log all messages at their threshold level or higher, i.e. an appender with threshold INFO will log INFO, WARN, ERROR and FATAL messages but not DEBUG. If you want to log only INFO messages but not WARN and above then you need to use a LevelMatchFilter.

You will also need to set your root logger priority to DEBUG, otherwise it will only send ERROR and FATAL messages to its appenders and your DEBUG and INFO files will be empty.

How to use the same logger to log different levels to console + logfile?

Appender based configuration

Configuring the log levels per each appender has to be done separately unless it is same as the root level configuration. Below sample log4.properties file is configured to log INFO and above into the console, but only ERROR and above into the file.

log4j.appender.[appender-name].Threshold=[Level]

Look at the last line of the below example (from "How to integrate log4j with your Java project").

# root level configurations 
log4j.rootLogger=INFO,console,file

# configuration for console outputs
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout

# configuration for file output (into a file named messages.log)
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=messages.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout

# threshold for file output
log4j.appender.file.Threshold=ERROR

Package based log levels

Any of the followings will help.

log4j.logger.[package]=[Level]
log4j.logger.[package]=[Level], [Appender]

As an example:

log4j.logger.org.apache.cxf=INFO, console

Log4j set a different logging level for each appender

To limit logging level on specific appender in log4j2 you should use ThresholdFilter element of an appender.

In your case log4j2.xml file will look like:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout>
<Pattern>%d %level %msg%n</Pattern>
</PatternLayout>
</Console>

<RollingFile name="Log" fileName="log/Log.log" filePattern="log/Log-%d{yyyy-MM-dd}-%i.log" append="false">
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout>
<Pattern>%d %level %msg%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>

<Loggers>
<Root level="info">
<AppenderRef ref="Console" />
<AppenderRef ref="Log" />
</Root>
</Loggers>
</Configuration>

Here is a simple test:

public class Log4jTest {
private static final Logger logger = LogManager.getLogger(Log4jTest.class);

public static void main(String[] args) {
logger.debug("Debug");
logger.info("Info");
logger.warn("Warning");
logger.error("Error");
logger.fatal("Fatal");
}
}

Console output:

2020-02-25 12:33:50,587 ERROR Error
2020-02-25 12:33:50,589 FATAL Fatal

Log.log contents:

2020-02-25 12:33:50,585 INFO Info
2020-02-25 12:33:50,587 WARN Warning
2020-02-25 12:33:50,587 ERROR Error
2020-02-25 12:33:50,589 FATAL Fatal

In first version of log4j it was Threshold property of appender. On how to solve the same in log4j see the answer on question.

With aid of filters Log4j2 allows to configure the output to a specific appender much more flexible then log4j.

Log different levels in different files using Dropwizard

Dropwizard has its own logging configuration, and it supports adding filters by writing FilterFactory classes.

For example, here is a FilterFactory that filters out everything but ERROR level log events:

@JsonTypeName("error-only")
public class ErrorLogFilter implements FilterFactory<ILoggingEvent> {

@Override
public Filter<ILoggingEvent> build() {
return new Filter<ILoggingEvent>() {
@Override
public FilterReply decide(ILoggingEvent event) {
if (event.getLevel().equals(Level.ERROR)) {
return FilterReply.NEUTRAL;
} else {
return FilterReply.DENY;
}
}
};

}
}

To register a factory, its fully qualified classname must be listed in META-INF/services/io.dropwizard.logging.filter.FilterFactory file.

And the configuration to get one of the file appenders to use it, would be like this:

  - type: file
threshold: ERROR
logFormat: '%date{dd-MM-yyyy HH:mm:ss.SSS} %X{X-Request-Id} [%thread] %-5level %logger{36} - %msg%n'
currentLogFilename: .../error.log
archivedLogFilenamePattern: .../error-%i.log.gz
archivedFileCount: 2
timeZone: IST
maxFileSize: 100MB
filterFactories:
- type: error-only


Related Topics



Leave a reply



Submit