Selective Suppression of Log Messages
- by Duncan Mills
Those of you who regularly read this blog will probably have noticed that I have a strange predilection for logging related topics, so why break this habit I ask?
Anyway here's an issue which came up recently that I thought was a good one to mention in a brief post. The scenario really applies to production applications where you are seeing entries in the log files which are harmless, you know why they are there and are happy to ignore them, but at the same time you either can't or don't want to risk changing the deployed code to "fix" it to remove the underlying cause. (I'm not judging here). The good news is that the logging mechanism provides a filtering capability which can be applied to a particular logger to selectively "let a message through" or suppress it. This is the technique outlined below.
First Create Your Filter
You create a logging filter by implementing the java.util.logging.Filter interface. This is a very simple interface and basically defines one method isLoggable() which simply has to return a boolean value. A return of false will suppress that particular log message and not pass it onto the handler.
The method is passed the log record of type java.util.logging.LogRecord which provides you with access to everything you need to decide if you want to let this log message pass through or not, for example getLoggerName(), getMessage() and so on.
So an example implementation might look like this if we wanted to filter out all the log messages that start with the string "DEBUG" when the logging level is not set to FINEST:
public class MyLoggingFilter implements Filter {
public boolean isLoggable(LogRecord record) {
if ( !record.getLevel().equals(Level.FINEST)
&& record.getMessage().startsWith("DEBUG")){
return false;
}
return true;
}
}
Deploying
This code needs to be put into a JAR and added to your WebLogic classpath. It's too late to load it as part of an application, so instead you need to put the JAR file into the WebLogic classpath using a mechanism such as the PRE_CLASSPATH setting in your domain setDomainEnv script. Then restart WLS of course.
Using
The final piece if to actually assign the filter. The simplest way to do this is to add the filter attribute to the logger definition in the logging.xml file. For example, you may choose to define a logger for a specific class that is raising these messages and only apply the filter in that case.
<logger name="some.vendor.adf.ClassICantChange"
filter="oracle.demo.MyLoggingFilter"/>
You can also apply the filter using WLST if you want a more script-y solution.