Blogging about Logging
I recently discovered a really nice package in Java – java.util.logging. Classes inside this package make adding logging functionality to your application both intuitively simple and fun. Here what I would like to think to be a short guide to using the package.
The very first thing you need to understand that there may be multiple loggers active in a Java application at a given time. Each such logger has a name associated with it. The names are hierarchical – you have the concept of a logged being the sibling or the parent of another logger. We will come to how that exactly works in a minute. Every logger has one or more handlers associated with it. It is these handlers which decide what exactly happens when you log a message (for example the handler may write to a file or print the messages out to the PrintStream). By default a logger also uses the handlers registered with its parents, recursively. You can change this behavior if you want to.
A global namespace is maintained containing the names of all the loggers. The logger names follow a dot-separated convention, somewhat like the one followed by the Java packaging system. This means that “parent.someChild” is a child of “parent” while “parent.someChild.someGrandChild” is a child of “parent.someChild“. “parent.sister” and “parent.brother” are siblings. “” is the root – the parent of each and every logger, either directly or indirectly.
Every logger has a Level associated with it – the minimum required urgency of a message for it to actually get logged. Similarly every log you make also have an associated Level, underlining the measure of its urgency. For instance if you wish your logger to log only the very critical messages you may set the level of the logger to Level.SEVERE or to Level.WARNING. There are other levels too, like Level.FINE and Level.INFO. You may set the level of a logger to Level.ALL or to Level.OFF to log all messages or no messages at all respectively.
The best part about the system is that you do not need to pass around objects – since there is a one to one mapping from the logger names to logger objects in global namespace, you can simply pull out the Logger associated with a name using Logger.getLogger (String name). The first call to Logger.getLogger ("mylogger") will create a new logger and return it while subsequent calls will simply return the previously constructed Logger instance.
So if you need to log from within your application you basically create Logger instances from inside each module you wish to log somewhat like Logger theLogger = Logger.getLogger ("myproject.thisModule"). Now you can use this object in your code – theLogger.warning ("Something happened"). In the application initialization code you have the liberty of setting the Levels of each logger to control what all information gets logged. You also have the freedom to write custom Filters using which you can control exactly what all is logged.
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.