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.

22 Comments »

  1. Great example !!! Thank you

    Comment by Zhurba — April 10, 2007 @ 9:04 am

  2. Glad to know, it helped you

    Comment by jaikiran — April 10, 2007 @ 10:39 am

  3. It’s good. If make more comments, that will be better than just provide source code. Thanks.

    Comment by wynton — June 28, 2007 @ 8:45 pm

  4. I got console info as follow. What’s the problem?

    Got the logger. Invoking log() method
    Wrote the log with my trace level

    log4j:WARN No appenders could be found for logger (org.myapp.core.TestMyLogLevel).
    log4j:WARN Please initialize the log4j system properly.

    Wrote the log with debug level

    Comment by wynton — June 28, 2007 @ 10:13 pm

  5. It means that the log4j.xml or log4j.properties file was not found in the classpath of the application. Have a look at http://jaitechwriteups.blogspot.com/2006/07/i-get-log4jwarn-no-appenders-could-be.html
    for more details

    Comment by jaikiran — June 28, 2007 @ 10:28 pm

  6. It’s a great example
    How can i write the same thing using log4j.properties instead of log4j.xml

    Comment by priya — December 8, 2007 @ 7:06 am

  7. in log4j.properties:

    log4j.logger.org.myapp=MY_TRACE#org.myapp.log.MyTraceLevel FILE

    instead of

    Comment by joel — December 31, 2007 @ 10:12 am

  8. siemano!

    Comment by prof — February 21, 2008 @ 12:20 pm

  9. Thanks for the tutorial. I have been going over this and have setup two loggers, one that would filter between trace – fatal. I created a custom logger just for query monitoring, called DAO. What I am finding is the dao log file is just getting debug logging.
    I tried messing with the filter parameters and setting a min and max, but still only debug. What I am wondering is if the int traceLevel (its arg3 in your constructor) is set to 7, that is the traceLevel for Debug, correct?

    Also in the log4j limited documentation, it mentions that extending the Level class is not the correct way, that there is a better way. But after searching google till my fingers are numb, I can’t find anything about the “better” 😉 … any ideas?
    Thanks this is one of the better tutorials on this.
    ~ JM

    Comment by JohnM — February 26, 2008 @ 10:26 pm

  10. Thanks for the tutorial.

    Could you explain to us why you put 7 for the syslogEquivalent parameter ?

    public static final Level MY_TRACE = new MyTraceLevel(MY_TRACE_INT,”MY_TRACE”,7);

    Comment by Olivier — April 29, 2008 @ 9:46 am

  11. hey… Can i write my own logger?? pls provide the code

    Comment by Ajay Verma — June 18, 2008 @ 11:40 am

  12. I want to create a custom logger… i want an example so that i can create it.. pls help me.

    Comment by Ajay Verma — June 18, 2008 @ 11:46 am

  13. To Olivier,

    For information on syslog levels, see this : http://www.kiwisyslog.com/kb/info:-syslog-message-levels/

    7 is for debug in syslog

    Comment by Pascal — November 18, 2008 @ 10:11 am

  14. I am not able to write log which i write in the traditional log4j way i.e. logger.MyTraceLevel(“Log trace level”);

    Can you please tell me what I am missing..

    Thanks & Regards,
    Pankaj

    Comment by pankaj — December 12, 2008 @ 11:48 am

    • log4j does not have a method called MyTraceLevel(String str). It only has Debug(String str), Info(String str)… Also, these are static methods and so there is no polymorphic behaviour that you are expecting.

      Comment by NGSundar — July 2, 2010 @ 12:18 am

  15. Your blog is so informative … ..I just bookmarked you….keep up the good work!!!!

    Hey, I found your blog in a new directory of blogs. I dont know how your blog came up, must have been a typo, anyway cool blog, I bookmarked you. 🙂

    Robert Shumake

    Comment by Robert Shumake — February 3, 2010 @ 9:11 am

  16. Hi, really fantastic tutorial.
    Facing an issue while doing the implementation:
    I want my custom level to be detected for sending mail. for this i defined my new SMTPAppender and added my custom level in it as “threshold” value and as per you also defined the category in the xml file with priority value as INFO but still the mail is not sent??? why ?

    Although when i define “threshold” as INFO the info statements are successfully sent in mail.

    what i am missing can you tell me?

    Comment by Bhupendra — May 11, 2010 @ 11:08 am

  17. I just using jboss 4.2
    and got this erros :
    log4j:ERROR Could not create level [MY_TRACE]. Reported error follows.
    java.lang.ClassNotFoundException: XXX.XXX.XXX.utils.MyTraceLevel

    any suggestion?

    Comment by priasa — August 22, 2010 @ 4:40 am

  18. Nice job! Thanks a lot !

    Comment by jacky — August 23, 2010 @ 8:19 am

  19. Hi,Nice work.Could u tell me..How to send email in custom level loggers using log4j?

    Comment by Bala — December 9, 2010 @ 7:18 pm

  20. punk

    Comment by Mard — April 20, 2011 @ 4:27 pm


RSS feed for comments on this post. TrackBack URI

Leave a reply to Bhupendra Cancel reply

Blog at WordPress.com.