My Wiki

July 12, 2006

Create your own logging level in log4j

Filed under: Log4j — jaikiran @ 2:22 am

If you need to add your own logging level in log4j, then you can do it as follows. You will have to create your own class which will extend from Level. Here’s a sample code for the same:

MyTraceLevel.java:

package org.myapp.log;
import org.apache.log4j.Level;
/**  
 * My own {@link org.apache.log4j.Level} for logging.  
 *  
 * @author Jaikiran Pai  
 *  
 */  
public class MyTraceLevel extends Level {  
     
    /**  
     * Value of my trace level. This value is lesser than {@link org.apache.log4j.Priority#DEBUG_INT}  
     * and higher than {@link org.apache.log4j.Level#TRACE_INT}  
     */  
    public static final int MY_TRACE_INT = DEBUG_INT - 10;  
     
    /**  
     * {@link Level} representing my log level  
     */  
    public static final Level MY_TRACE = new MyTraceLevel(MY_TRACE_INT,"MY_TRACE",7);
    /**  
     * Constructor  
     *  
     * @param arg0  
     * @param arg1  
     * @param arg2  
     */  
    protected MyTraceLevel(int arg0, String arg1, int arg2) {  
        super(arg0, arg1, arg2);
    }  
     
    /**  
     * Checks whether <code>sArg</code> is "MY_TRACE" level. If yes then returns {@link MyTraceLevel#MY_TRACE},  
     * else calls {@link MyTraceLevel#toLevel(String, Level)} passing it {@link Level#DEBUG} as the defaultLevel  
     *  
     * @see Level#toLevel(java.lang.String)  
     * @see Level#toLevel(java.lang.String, org.apache.log4j.Level)  
     *  
     */  
    public static Level toLevel(String sArg) {  
        if (sArg != null && sArg.toUpperCase().equals("MY_TRACE")) {  
            return MY_TRACE;  
        }  
        return (Level) toLevel(sArg, Level.DEBUG);  
    }
    /**  
     * Checks whether <code>val</code> is {@link MyTraceLevel#MY_TRACE_INT}. If yes then returns {@link MyTraceLevel#MY_TRACE},  
     * else calls {@link MyTraceLevel#toLevel(int, Level)} passing it {@link Level#DEBUG} as the defaultLevel  
     *  
     * @see Level#toLevel(int)  
     * @see Level#toLevel(int, org.apache.log4j.Level)  
     *  
     */  
    public static Level toLevel(int val) {  
        if (val == MY_TRACE_INT) {  
            return MY_TRACE;  
        }  
        return (Level) toLevel(val, Level.DEBUG);  
    }
    /**  
     * Checks whether <code>val</code> is {@link MyTraceLevel#MY_TRACE_INT}. If yes then returns {@link MyTraceLevel#MY_TRACE},  
     * else calls {@link Level#toLevel(int, org.apache.log4j.Level)}  
     *  
     * @see Level#toLevel(int, org.apache.log4j.Level)  
     */  
    public static Level toLevel(int val, Level defaultLevel) {  
        if (val == MY_TRACE_INT) {  
            return MY_TRACE;  
        }  
        return Level.toLevel(val,defaultLevel);  
    }
    /**  
     * Checks whether <code>sArg</code> is "MY_TRACE" level. If yes then returns {@link MyTraceLevel#MY_TRACE},  
     * else calls {@link Level#toLevel(java.lang.String, org.apache.log4j.Level)}  
     *  
     * @see Level#toLevel(java.lang.String, org.apache.log4j.Level)  
     */  
    public static Level toLevel(String sArg, Level defaultLevel) {                   
    if(sArg != null && sArg.toUpperCase().equals("MY_TRACE")) {  
        return MY_TRACE;  
    }  
    return Level.toLevel(sArg,defaultLevel);  
 }  
     
}
 

Now here’s the log4j.xml configuration file:

<?xml version="1.0" encoding="UTF-8"?>            

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">            

<!-- ===================================================================== -->            

<!-- -->            

<!-- Log4j Configuration -->            

<!-- -->            

<!-- ===================================================================== -->            

<!-- $Id: log4j.xml,v 1.13.2.8 2003/09/23 14:16:27 slaboure Exp $ -->            

<!--            

| For more configuration infromation and examples see the Jakarta Log4j            

| owebsite: http://jakarta.apache.org/log4j            

-->            

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">            

<!-- ================================= -->            

<!-- Preserve messages in a local file -->            

<!-- ================================= -->            

<!-- A size based rolling appender -->            

<appender name="FILE" class="org.apache.log4j.FileAppender">            

<param name="File" value="D:/log/myLogFile.log"/>            

<param name="Append" value="false"/>            

<layout class="org.apache.log4j.PatternLayout">            

<param name="ConversionPattern" value="%d{ISO8601} %-5p [%c] %m%n"/>            

</layout>            

</appender>            

<!-- ============================== -->            

<!-- Append messages to the console -->            

<!-- ============================== -->            

<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">            

<param name="Target" value="System.out"/>            

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

<layout class="org.apache.log4j.PatternLayout">            

<!-- The default pattern: Date Priority [Category] Messagen -->            

<param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] %m%n"/>            

</layout>            

</appender>            

<!-- ================ -->            

<!-- Limit categories -->            

<!-- ================ -->            

<category name="org.myapp">            

<priority value="MY_TRACE" class="org.myapp.log.MyTraceLevel" />            

<appender-ref ref="FILE"/>            

</category>            

<!-- ======================= -->            

<!-- Setup the Root category -->            

<!-- ======================= -->            

<root>            

<appender-ref ref="CONSOLE"/>            

</root>            

</log4j:configuration>            

Here’s a test program which can be used for testing whether the new log level that you introduced is being identified or not:

TestMyLogLevel.java:

package org.myapp.core;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.myapp.log.MyTraceLevel;

/**
 * Tests whether the new log level {@link org.myapp.log.MyTraceLevel#MY_TRACE} is working
 *
 * @author Jaikiran Pai
 *
 */
public class TestMyLogLevel {

    /**
     * Writes a log message with {@link org.myapp.log.MyTraceLevel#MY_TRACE} and another message
     * with {@link Level#DEBUG}
     *
     * @param args
     */
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(TestMyLogLevel.class.getName());
        System.out.println(“Got the logger. Invoking log() method”);
        logger.log(MyTraceLevel.MY_TRACE,”Did i get into the log file?”);
        System.out.println(“Wrote the log with my trace level”);
        logger.log(Level.DEBUG ,”I am a debug message”);
        System.out.println(“Wrote the log with debug level”);
    }
}
Finally, here’s the log file that got generated:
2006-07-12 13:45:40,633 MY_TRACE [org.myapp.core.TestMyLogLevel] I am MY_TRACE log
2006-07-12 13:45:40,633 DEBUG [org.myapp.core.TestMyLogLevel] I am a debug message

Points to note:
The int value that you specify for your log level is important. Here i have defined “MY_TRACE” log level is to be higher than the DEBUG level but lower than the TRACE level provided by log4j. So whenever you have set a priority level to DEBUG on the category(in your log4j.xml file), the MY_TRACE level logs will *NOT* make it to the log file.

July 5, 2006

I get “log4j:WARN No appenders could be found for logger” message

Filed under: Log4j — jaikiran @ 7:57 am

While using log4j in your application, sometimes you might encounter the following message:

log4j:WARN No appenders could be found for logger(somePackageName.someClassName).
log4j:WARN Please initialize the log4j system properly.

The reason why you see this message is that your log4j configuration file(i.e. log4j.xml or log4j.properties) is NOT found in the classpath. Placing the log4j configuration file in the applications classpath should solve the issue. If you want to find out how log4j tries to configure itself, have a look at my earlier post :

Know how log4j tries to configure itself

July 4, 2006

Know how log4j tries to configure itself

Filed under: Log4j — jaikiran @ 2:44 am

Large number of applications use log4j for logging. Sometimes you may encounter cases where you sense that log4j is using some other configurations, other than the one that you expected it to use. You can debug the same by switching on the debug flag on log4j. Here’s how you can do it:

Add -Dlog4j.debug to the command line. log4j will output info to std. out. telling you how it tries to configure itself.

Blog at WordPress.com.