Search

Showing posts with label Log4j. Show all posts
Showing posts with label Log4j. Show all posts

Multiple Appenders Using XML File example

In this example we will see how to create more than one appender using xml configuration file. This example is similar to the one we saw before using the properties file (example). So I will simply compare both.
The following code shows the log4j.properties file we used in the previous example.
log4j.rootLogger=DEBUG, CA, FA

#Console Appender
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

#File Appender
log4j.appender.FA=org.apache.log4j.FileAppender
log4j.appender.FA.File=sample.log
log4j.appender.FA.layout=org.apache.log4j.PatternLayout
log4j.appender.FA.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

# Set the logger level of File Appender to WARN
log4j.appender.FA.Threshold = WARN
The following code shows the corresponding log4j.xml file.
<?xml version="0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="CA" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-4r [%t] %-5p %c %x - %m%n" />
</layout>
</appender>
<appender name="FA" class="org.apache.log4j.FileAppender">
<param name="File" value="sample.log"/>
<param name="Threshold" value="WARN"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-4r [%t] %-5p %c %x - %m%n" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="CA" />
<appender-ref ref="FA" />
</root>
</log4j:configuration>


Log4j XML Configuration

We can also use XML file to configure log4j. In the previous example we saw how we can do this using the properties file, everything remains the same except that we use the XML configuration file here.
The following code shows the log4j.properties file we used in the previous example.
log4j.rootLogger=DEBUG, CA
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
The following code shows the corresponding log4j.xml file.
<?xml version="0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="CA" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-4r [%t] %-5p %c %x - %m%n" />
</layout>
</appender>
<root>
<level value="debug" />
<appender-ref ref="CA" />
</root>
</log4j:configuration>
To configure log4j using xml file we use DOMConfigurator.configure() method. 
package com.vaannila.helloworld;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;

public class HelloWorld {

static Logger logger = Logger.getLogger(HelloWorld.class);

public static void main(String[] args) {
DOMConfigurator.configure("log4j.xml");
logger.debug("Sample debug message");
logger.info("Sample info message");
logger.warn("Sample warn message");
logger.error("Sample error message");
logger.fatal("Sample fatal message");
}
}
Here is the output of the above code. 
0    [main] DEBUG com.vaannila.helloworld.HelloWorld  - Sample debug message
0    [main] INFO  com.vaannila.helloworld.HelloWorld  - Sample info message
0    [main] WARN  com.vaannila.helloworld.HelloWorld  - Sample warn message
0    [main] ERROR com.vaannila.helloworld.HelloWorld  - Sample error message
0    [main] FATAL com.vaannila.helloworld.HelloWorld  - Sample fatal message

Log4j File Appender

A typical requirement in the project is to log different modules in different log files. For instance in this example we have two modules one for the admin and other for reports.
To do this we create two seperate FileAppenders and associate them with each package.
package com.vaannila.admin;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import com.vaannila.report.SampleReport;

public class SampleAdmin {

static Logger logger = Logger.getLogger(SampleAdmin.class);

public static void main(String[] args) {
PropertyConfigurator.configure("log4j.properties");
logger.debug("Sample debug message");
logger.info("Sample info message");
logger.warn("Sample warn message");
logger.error("Sample error message");
logger.fatal("Sample fatal message");
SampleReport obj = new SampleReport();
obj.generateReport();
}

}
Here instead of associating the appenders to the rootLogger we associate it with different packages. The AdminFileAppender is linked with the admin package and the ReportFileAppender is linked with the report package. This means all the log entries in the admin module will be logged in the admin.logfile and all the log entries in the report module will be logged in the report.log file. You can also set different logger levels for each package, here for the admin package it is set to WARN and for the report package it is set to DEBUG. The rootLogger will be by default set to the logger level DEBUG, so this statement "log4j.rootLogger=DEBUG" is there only for your understanding purpose and it is not necessary.
In this example we have two classes SampleAdmin class in the admin package and SampleReportclass in the report package.
package com.vaannila.admin;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import com.vaannila.report.SampleReport;

public class SampleAdmin {

static Logger logger = Logger.getLogger(SampleAdmin.class);

public static void main(String[] args) {
PropertyConfigurator.configure("log4j.properties");
logger.debug("Sample debug message");
logger.info("Sample info message");
logger.warn("Sample warn message");
logger.error("Sample error message");
logger.fatal("Sample fatal message");
SampleReport obj = new SampleReport();
obj.generateReport();
}

}
package com.vaannila.report;

import org.apache.log4j.Logger;

public class SampleReport {

static Logger logger = Logger.getLogger(SampleReport.class);

public void generateReport()
{
logger.debug("Sample debug message");
logger.info("Sample info message");
logger.warn("Sample warn message");
logger.error("Sample error message");
logger.fatal("Sample fatal message");
}
}
After executing the program, the contents of admin.log file. 
0    [main] WARN  com.vaannila.admin.SampleAdmin  - Sample warn message
0    [main] ERROR com.vaannila.admin.SampleAdmin  - Sample error message
0    [main] FATAL com.vaannila.admin.SampleAdmin  - Sample fatal message
The contents of report.log file.
0    [main] DEBUG com.vaannila.report.SampleReport  - Sample debug message
0    [main] INFO  com.vaannila.report.SampleReport  - Sample info message
0    [main] WARN  com.vaannila.report.SampleReport  - Sample warn message
0    [main] ERROR com.vaannila.report.SampleReport  - Sample error message
0    [main] FATAL com.vaannila.report.SampleReport  - Sample fatal message
It's not necessary to apply the logger level to each package, by default the rootLogger level will be inherited. 
log4j.logger.com.vaannila.admin=,AdminFileAppender
log4j.logger.com.vaannila.report=,ReportFileAppender
Insted of applying a logger level, the field is left blank so the rootLogger level ("DEBUG") will be inheritted.
If you associate a ConsoleAppender to the rootLogger then all the log entries in both the admin andreport packages will be log on the console.
log4j.rootLogger=DEBUG, CA

# 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

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

log4j.logger.com.vaannila.admin=WARN,AdminFileAppender
log4j.logger.com.vaannila.report=DEBUG,ReportFileAppender
On executing the example you will see the following output on the console. 
0    [main] WARN  com.vaannila.admin.SampleAdmin  - Sample warn message
0    [main] ERROR com.vaannila.admin.SampleAdmin  - Sample error message
0    [main] FATAL com.vaannila.admin.SampleAdmin  - Sample fatal message
0    [main] DEBUG com.vaannila.report.SampleReport  - Sample debug message
0    [main] INFO  com.vaannila.report.SampleReport  - Sample info message
0    [main] WARN  com.vaannila.report.SampleReport  - Sample warn message
0    [main] ERROR com.vaannila.report.SampleReport  - Sample error message
16   [main] FATAL com.vaannila.report.SampleReport  - Sample fatal message
If you want the log messages from all the packages to be logged then add the corresponding appender to the rootLogger, if you want the appender to be associated with a specific package then apply only to that package. If you do it in both the places then the log entries will be repeated.
The directory structure of the example is shown below.

Download Log4j examples source code