Filters
When you write the code to send a logging message to a Logger object, you often decide, at the time you’re writing the code, what level the logging message should be (the logging API certainly allows you to devise more complex systems wherein the level of the message can be determined dynamically, but this is less common in practice). The Logger object has a level that can be set so that it can decide what level of message to accept; all others will be ignored. This can be thought of as a basic filtering functionality, and it’s often all you need.
Sometimes, however, you need more sophisticated filtering so that you can decide whether to accept or reject a message based on something more than just the current level. To accomplish this you can write custom Filter objects. Filter is an interface that has a single method, boolean isLoggable(LogRecord record), which decides whether or not this particular LogRecord is interesting enough to report.
Once you create a Filter, you register it with either a Logger or a Handler by using the setFilter( ) method. For example, suppose you’d like to only log reports about Ducks:
//: c15:SimpleFilter.java
import com.bruceeckel.simpletest.*;
import java.util.logging.*;
public class SimpleFilter {
private static Test monitor = new Test();
private static Logger logger =
Logger.getLogger("SimpleFilter");
static class Duck {};
static class Wombat {};
static void sendLogMessages() {
logger.log(Level.WARNING,
"A duck in the house!", new Duck());
logger.log(Level.WARNING,
"A Wombat at large!", new Wombat());
}
public static void main(String[] args) {
sendLogMessages();
logger.setFilter(new Filter() {
public boolean isLoggable(LogRecord record) {
Object[] params = record.getParameters();
if(params == null)
return true; // No parameters
if(record.getParameters()[0] instanceof Duck)
return true; // Only log Ducks
return false;
}
});
logger.info("After setting filter..");
sendLogMessages();
monitor.expect(new String[] {
"%% .* SimpleFilter sendLogMessages",
"WARNING: A duck in the house!",
"%% .* SimpleFilter sendLogMessages",
"WARNING: A Wombat at large!",
"%% .* SimpleFilter main",
"INFO: After setting filter..",
"%% .* SimpleFilter sendLogMessages",
"WARNING: A duck in the house!"
});
}
} ///:~
Before setting the Filter, messages about Ducks and Wombats are reported. The Filter is created as an anonymous inner class that looks at the LogRecord parameter to see if a Duck was passed as an extra argument to the log( ) method. If so, it returns true to indicate that the message should be processed.
Notice that the signature of getParameters( ) says that it will return an Object[]. However, if no additional arguments have been passed to the log( ) method, getParameters( ) will return null (in violation of its signature—this is a bad programming practice). So instead of assuming that an array is returned (as promised) and checking to see if it is of zero length, we must check for null. If you don’t do this correctly, then the call to logger.info( ) will cause an exception to be thrown.