Friday, June 02, 2006

Captain's Log

The old fashioned way to tell what's happening to your program is write a print statement. In Java, as in C, there are two ways to print that statement. You can print it to standard output, which might buffer the output, or to standard error, which should not.

How long would it take for you to explain how System.out.println works? A few minutes? Tell a person that each object as a toString() method. If it's been overridden, it prints something reasonable. If not, it looks like a fancy pointer.

Nice and simple.

These days, people tell you that the way to write debugging statements is to use a logger. A logger may be one (typically) more classes. The most popular one in use for Java is log4j. Loggers have the notion of an appender. This is what's used to send data to the console, a file, a database, or whereever. Most people use the one built in.

A good book on loggers ought to explain why this monstrosity was invented. Most of them don't. They assume you want to use loggers and start delving into details. The writers have often used loggers for so long that they don't spend much time justifying why it is the way it is. They don't complain about how it could be better, or why this sucks or that. Instead, they figure you have to use it, so they talk about it.

There's enough people who find doing something complex rather than something simple aggravating, that a compelling case had better be made to use something that could fill up a 200 page book when only two or three pages would be needed with the system before.

log4j uses a weirdish notion of inheritance, treating "classes" as a kind of path. Thus, if you have foo.bar as some package and a class that has the package foo.bar.FunStuff and assign it a logger based on its package plus class name, it will inherit the logger attributes from foo.bar. Were you to create a package with a longer name like foo.bar.baz.AnotherClass, it can inherit from this.

In addition, the loggers use various warning levels to set filters on. log4j has something like 5 different warning levels. Which level a logger uses depends on an external file (usually) which is either a Java properties file or an XML equivalent.

Already, you can see that it's kind of messy.

I'd rather use tags to identify "loggers". Thus, when you write an output, you can have a list of tags like database or gui or some such. The output would then listen for the tags. Thus, you could have a console output that listens for gui and only prints that out. I might jettison warning levels and use well-known tags instead.

One of the more hideous features of log4j that defies explanation is the addivity feature. If you don't set it to false, your root logger will often print certain things twice. Books have to explain how to get rid of this, which ought to indicate something is wrong.

One of these days they should have something better than these loggers. They attempt to solve a problem, but the overhead seems unimaginably crazy, and when you explain it to someone who's only ever used simple print statements, they're likely to cringe at this overengineered solution.

Alas, like Ant, everyone uses this in Java, so we're left to deal with this, or be seen as hopelessly simple-minded.

No comments: