Creating Multiple Log Files of Different Content with Log4J

How to create multiple log files of different content with log4j

Finally I found the way of doing this.

# Root logger option
log4j.rootLogger=TRACE, stdout, file

log4j.category.testngLogger=DEBUG, testng
log4j.additivity.testngLogger=false

In rootLogger, that is like a father of all logs. It inherit by default. Root logger option should be like that.


If you additivity set to false it will never goes to rootLogger

In log4j.xml file it will goes like this.

<logger name="testngLogger" additivity="false">
<level value="DEBUG" />
<appender-ref ref="testngLogger" />
</logger>

<root>
<priority value="INFO" />
<appender-ref ref="CONSOLE" />
<appender-ref ref="fileLogger" />
</root>

In Apache Log4J, Is there a way to simply create multiple log files on the fly, rather than appending to one log file?

Yes, you can use the RoutingAppender. See this question for details: Log4j2: Dynamic creation of log files for multiple logs

Multiple log files with log4j

Of cource, use different FileAppenders
Example from internet:

log4j.rootLogger=DEBUG

# AdminFileAppender - used to log messages in the admin.log file.
log4j.appender.AdminFileAppender=org.apache.log4j.FileAppender

log4j.appender.AdminFileAppender.File=admin.log

log4j.appender.AdminFileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.AdminFileAppender.layout.ConversionPattern= %-4r [%t] %-5p %c %x - %m%n

# ReportFileAppender - used to log messages in the report.log file.
log4j.appender.ReportFileAppender=org.apache.log4j.FileAppender

log4j.appender.ReportFileAppender.File=report.log

log4j.appender.ReportFileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.ReportFileAppender.layout.ConversionPattern= %-4r [%t] %-5p %c %x - %m%n

log4j.logger.com.vaannila.admin=WARN,AdminFileAppender
log4j.logger.com.vaannila.report=DEBUG,ReportFileAppender

Now you can log to admin.log Logger.getLogger("com.vaannila.admin").log("To admin log") and to report log Logger.getLogger("com.vaannila.report").log("To report log")

How to create multiple log files in log4j2 using property file?

Please set additivity=false for both named loggers.

Also, add a root logger configuration to tell Log4j2 where to send the logging calls other than the “file1” and “file2” loggers:

rootLogger.level = info
rootLogger.appenderRef.stdout.ref = STDOUT

Also, give your named loggers a unique prefix:

logger.aaa.name = file1
logger.aaa.additivity = false
logger.aaa.level = debug
logger.aaa.appenderRef.rrr.ref = RollingFile1

logger.bbb.name = file2
logger.bbb.additivity = false
logger.bbb.level = debug
logger.bbb.appenderRef.sss.ref = RollingFile2

Creating multiple log instances using log4j to output log files in separate locations

It seems that creating a new appender for each new instance is necessary, since each instance needs to print to a different file output location. I solved this problem by creating a generateLogger() method with the necessary parameters to create new loggers and appenders programmitcally. If you will notice the first parameter contains the name of a parent logger. If I include this in my new logger name, it will inherit the properties of its parent, which is configured in my master.properties file, and vice versa. For example, if my parent logger is "Broker" and my logger name is "Broker1", then the full loggerName will be "Broker.Broker1". This way I can track all the brokers in one log file while also having separate log files for each broker in their own separate file output locations. Not to mention, this method can be re-used with many different kinds of Logs using different parent loggers. Though the parent Logger is not even necessary if you choose. If you choose to not have a parent Logger, simply delete it from the method and disregard my master.properties file.

public Logger generateLogger(String parent, String name, String logDirectory, String filePattern, String fileThreshold) {
// TODO Auto-generated method stub

//Create Logger
String loggerName = parent + "." + name;
Logger log = Logger.getLogger(loggerName);

//Create Logging File Appender
RollingFileAppender fileApp = new RollingFileAppender();
fileApp.setName("Broker." + loggerName + "_FileAppender");
fileApp.setFile(logDirectory +"/"+ name+".log");
fileApp.setLayout(new PatternLayout(filePattern));
fileApp.setThreshold(Level.toLevel(fileThreshold));
fileApp.setAppend(true);
fileApp.activateOptions();

log.addAppender(fileApp);

return log;
}

Here is the Broker logger configuration inside my master.properties file for reference.

log4j.logger.Broker=DEBUG, BrokerFile

# Broker Appenders
# Broker File Appender
log4j.appender.BrokerFile=org.apache.log4j.RollingFileAppender
log4j.appender.BrokerFile.File=C:/Documents and Settings/gr2cher/My Documents/KTLO/Java/CMInbound/BrokerLogs/Logs/Broker.log
log4j.appender.BrokerFile.MaxFileSize=1MB
log4j.appender.BrokerFile.MaxBackupIndex=1
log4j.appender.BrokerFile.layout=org.apache.log4j.PatternLayout
log4j.appender.BrokerFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
log4j.appender.BrokerFile.threshold=DEBUG

How to create multiple log file programatically in log4j2?

You said your objective is:

For each device I need to create a different log file to log it's communication with device.

There are many different ways to accomplish this without programmatic configuration. Programmatic configuration is bad because it forces you to depend on the logging implementation rather than the public interface.

For example you could use a context map key in conjunction with a Routing Appender to separate your logs, similar to the example I gave in another answer. Note that in the other answer I used the variable as the folder where the log is stored but you can use it for the log name if you wish.

Another way to do what you want would be to use a MapMessage as shown in the log4j2 manual.

Yet another way would be to use markers in combination with a RoutingAppender. Here is some example code for this approach:

package example;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;

public class LogLvlByMarkerMain {
private static final Logger log = LogManager.getLogger();
private static final Marker DEVICE1 = MarkerManager.getMarker("DEVICE1");
private static final Marker DEVICE2 = MarkerManager.getMarker("DEVICE2");

public static void main(String[] args) {
log.info(DEVICE1, "The first device got some input");
log.info(DEVICE2, "The second device now has input");
}
}

Configuration:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Routing name="MyRoutingAppender">
<Routes pattern="$${marker:}">
<Route>
<File
fileName="logs/${marker:}.txt"
name="appender-${marker:}">
<PatternLayout>
<Pattern>[%date{ISO8601}][%-5level][%t] %m%n</Pattern>
</PatternLayout>
</File>
</Route>
</Routes>
</Routing>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="[%date{ISO8601}][%-5level][%t] %m%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="example" level="TRACE" additivity="false">
<AppenderRef ref="STDOUT" />
<AppenderRef ref="MyRoutingAppender" />
</Logger>
<Root level="WARN">
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>

Output:

This will generate 2 log files - DEVICE1.txt and DEVICE2.txt as shown in the image below.

Generated Log Files

The first log will contain only messages that were marked as DEVICE1 and the second will contain only DEVICE2 logs.

I.e. the first log contains:

[2017-09-21T09:52:04,171][INFO ][main] The first device got some input

and the second contains:

[2017-09-21T09:52:04,176][INFO ][main] The second device now has input


Related Topics



Leave a reply



Submit