There is really no excuse for log4j. I've always said it was vastly too complex and somebody should be punished for it; today I almost wrote my own logging package it's behavior was so bad.
1) log4j does nothing when you don't have a proper configuration file. This is unacceptable--throwing away log messages is never a good idea, at least they should go to the console or /var/log4-rejects or be burned into the machine's bios or something...
2) log4j helpfully tells you what the name is of the logger that it couldn't figure out what to do with (as well as saying "please initialize log4j 'properly', gee thanks) but it doesn't tell you where it looked for the configuration file! This wouldn't be so bad if it was consistent at the way it fails, but it's not. You would have thought, you blundering idiot, that if you put the configuration file in the CLASSPATH directly, things would work. You'd be wrong. It appears that through some number of levels of indirection the classloader gets changed (see stupid flexibility in #5, below) and thus the CLASSPATH in your shell gets ignored. Lovely. So you must put the log4j.properties inside jar file that actually links against the logging cruft (see useless flexibility #4, below) to have it actually find the configuration file. I suspect that if you had the apache gene on chromosome 12 you would have intuitively guessed that was the case.
3) Minor side rant: The fact that the minimal useful configuration file is several lines long is pretty sad. You should be able to just put something like "BE SENSIBLE" in the file and have dump things to the terminal or send up flares from your machine or something that's likely to help a developer make forward progress. Oh, and don't forget your specification of the logging format--you can't possibly expect a logging package to choose something that critical for you.
4) It would be bad enough if log4j was our only burden to bear, but of course the apache folks had to add extra layers of indirection between me and my beloved log4j package. Three isn't a crowd here, let's add an arbitrary number of extra wheels! They have thoughtfully provided a meta-logging package (commons-logging) that allows multiple, true logging back-ends to work simultaneously (you getting this?). This is in case you need to switch out your logging package for one of the many (I'm sure) vastly more powerful implementations that somebody is fiendishly working on right now. In his mom's basement. Ugh. Log4j is bad enough, but allowing extra flexibility is just going to insure that I can't get anything useful to happen without a lifetime supply of Tums.
5) I would be remiss if I didn't mention that the underlying culprit here was actually the uselessly flexible XML parsing meta-infrastructure...oh, and that's from sun, another bunch that never seemed to have anything better to do than make things that should be simple, complex. Naturally, no meta infrastructure that allows you to dynamically load or choose your XML parser implementation at run-time (gee, I do that a lot) would be complete without a dependency on the meta logging layer! So, the poor soul that just wants to parse a config file in XML (which was the case here, where I was using someone else's code) ends up with this huge set of dependencies on meta-layers and true implementations that he/she doesn't even control and possibly has never heard of. Great, so there are at least 2 extra moving parts here, just to parse a config file. Sun, if you are listening and wondering why people are fleeing J2EE (and to some extent Java entirely), for Ruby on Rails this is the type of cruft that keeps people cursing your name. Oh, and that boil on your left buttock, that's from me.
6) The XML parsing infrastructure (the sun provided one that the poor sod who wrote this code never even new about) had one, final trick up it's sleeve: when it fails to parse a document correctly and is called from it's simple API (like 'parseDocument') it just exits. Now, overall, I'm in favor of programs not continuing to run when they can't run correctly--fail early, fail often, I always chant. However, when you are swallowing any error messages that the poor user could have possibly used to figure out what's wrong (see #2) then you are probably going to surprise the user a great deal by having problems simply stop. In other words, if you both fail to initialize the document and the logging infrastructure, you should either print something to the console before exiting or set the CPU afire to prevent the user from touching the machine and throwing it out the window. It's the least you could do.
Why all this anger, you may ask? I had edited the XML config file for a program that (inadvertently) used all this machinery and I had foolishly added a character to make a line like this:
<foo... /></foo>
Note the extra / I added causes the XML parse to fail and the rest, they say, is history. 5 hours of it, to be precise.
Comments