To use JUL as logging framework in an application we have just to change the application classpath, removing the previous SLF4J plugin jar and adding slf4j-jdk14-1.6.4.jar instead. This is enough to SLF4J to get that JUL is our requested logging target.
By default JUL will use its default configuration. Usually we'd like to specify our specific configuration, let's see an example.
I wrote a very simple configuration file, named logging.properties, containing this few lines:
#test log .level= ALL handlers= java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level= ALLAn hash character, '#', has the same meaning of of a double slash in Java: consider whatever is after, till the end of line, as a comment.
In the second line we see how to specify the generic log level for the application: all the messages have to be generated.
The third line is about which handler have to be used. The console handler is a simple one that sends the log messages to standard error. By default it prints only messages with severity info and above.
In the fourth line we configure the console handler to manage all the messages, overriding its standard behavior.
It is not overkilling, we have to specify both that all the messages have to be generated (line 2) and managed by our handler (line 4).
A simple way to use a JUL configuration file is passing it to Java from the command line:
> java -classpath .;C:/slf4j-1.6.4/slf4j-api-1.6.4.jar;C:/slf4j-1.6.4/slf4j-jdk14-1.6.4.jar -Djava.util.logging.config.file=logging.properties test.MyLogTesterWe asked java to run a class, test.MyLogTester, loading a file, logging.properties, as java.util.logging.config.file, so that it will be used to set the options for the JDK logger.
We can do the same programmatically. It could be handy to work in this way, for instance, to use different profiles without being forced to stop and restart the application:
Properties prop = System.getProperties(); prop.setProperty("java.util.logging.config.file", "logging.properties"); // 1 try { LogManager.getLogManager().readConfiguration(); } catch(Exception e) {} // 21. It doesn't make much sense to use an hard-coded file name, but this is just an example.
2. This error handling is very weak. We should have checked for IOException and SecurityException, and give some feedback to the user in case of failure.
A simple little method to check how the log behavior changes for different loggers and configurations:
void slf() { if (!log.isTraceEnabled()) System.out.println("Trace not enabled"); else log.trace("trace"); if (!log.isDebugEnabled()) System.out.println("Debug not enabled"); else log.debug("debug"); if (!log.isInfoEnabled()) System.out.println("Info not enabled"); else log.info("info"); if (!log.isWarnEnabled()) System.out.println("Trace not enabled"); else log.warn("warn"); if (!log.isErrorEnabled()) System.out.println("Error not enabled"); else log.error("error"); }It is interesting to check if a log level is enabled before calling the relevant log message, so that we can have a different output when testing different configuration files.
No comments:
Post a Comment