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 sArg 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 val 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 val 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 sArg 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, you will have to configure your log4j.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<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] Message\n -->
<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);
logger.log(MyTraceLevel.MY_TRACE,"I am MY_TRACE log");
logger.log(Level.DEBUG ,"I am a debug message");
}
}
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.