Logging abstraction is utterly pointless

I had always thought so but in the last week I’ve concluded with dynamite determination that logging abstraction is completely pointless. No. Benefit. Whatsoever. Could I be mistaken? No, if anything you’re probably still hanging on to Commons Logging because somebody told you how great it was, I don’t think anyone in their right mind would, after taking a step back and looking at the circumstances say, Hmmm, I really need to be careful and not commit myself to Log4J because God knows when Mark Womack and his team might pack it in and leave me hangin’. The same people who name their first born after Commons Logging classes commit themselves to products like IText, JFreeChart and GodKnowsWhat without ever thinking about abstraction. Raise your hand if you’re ever used IText and considered what happens if you want to switch your PDF generation tool? Nobody? So why the hell do we care so much about logging?

Luckily the answer is as simple as it is stupid: making a logging tool is so freaking easy that everybody’s got a homegrown one which they swear by and would never ditch even if they were offered ass in return (this just in, Logger just won the most used classname ever, it beat out Tester). So instead they use Commons Logging which gives them the feeling of not being such a big idiot with the added bonus of sleeping well at night knowing that they could eaaaasily switch to Log4J if they wanted to. What these poor saps don’t know is that switching between logging tools isn’t even that easy regardless of the abstraction, you still have to worry about configuring your tool which is a major pain in the ass if you want to actually stick to the proper log levels. Besides, nobody’s switching to anything, once you pick a logging framework you stick with it until the application is dead. Period. No exceptions. And if you happen to be switching your logging implementation so frequently that you need abstraction you suck at design and product evaluation.

Do you really care which of the two following imports you’d rather have shit on your code: org.apache.commons.logging or org.apache.log4j. Unless you have a thing for using commons packages (and some people do) you probably don’t give a rats ass. So with that in mind why don’t we save ourselves some trouble and just use Log4J, and as a bonus I’ll throw in the pro of Tomcat not barfing every time it sees two commons logging jars in its classpath, God forbid if they’re two different versions because then it starts giving you errors that make you regret ever even getting into Java.

The only way to beat Log4J is to have something out of the ever so trustworthy java.* packages do the logging for you. Luckily there’s JULI which is really great but unfortunately it’s documented about as poorly as Guice and isn’t marketed nearly as aggressively as that retard Duke (I really hate that son of a bitch, looks like a tooth with a big cavity). Besides, anytime anyone asks you to modify something in the JAVA_HOME directory to configure something red flags go up. Somebody please document how to load a config file from your classpath without specifying a -D option in JAVA_OPTS. I mean I’m configuring logging, not optimizing my garbage collection, yeeeesh.

Subscribe to Arsenalist's tech feed

Advertisements

24 thoughts on “Logging abstraction is utterly pointless

  1. Scott Howard

    The Tomcat/CL issue forced me to ditch logging abstraction. Haven’t checked Tomcat recently so don’t know if they fixed it.

    Reply
  2. WarpedJavaGuy

    Totally agree, who needs logging abstractions? They’re every multi class loading container’s worst enemy. Even the JCL over SLF4J solution doesn’t fix the class loading problem. It merely substitutes one JCL implementation for another (they all do). The class loading issues always remain. Better to use Log4J or Java Logging directly. The problem is that you don’t have that choice when your app server uses JCL.

    Reply
  3. Ivan Memruk

    I mostly agree, but slf4j has a plus compared with log4j in that it allows you to keep your dependencies which use commons-logging tame by using jcl-over-slf4j. In that case, you can also escape the commons-logging classloader hell.

    Reply
  4. WarpedJavaGuy

    I don’t know that you can escape the class loader hell? jcl-over-slf4j merely gives you yet another JCL implementation. That is: another version of the same JCL classes to further confuse all class loaders.

    Reply
  5. Ivan Memruk

    Nope. The strategy is to exclude any commons-logging instances (I mean jars) from your classpath and put there only the slf4j implementation. Then you can be sure all your commons-logging consumers use the slf4j flow.

    Reply
  6. Craig

    /me raises hand πŸ™‚
    I wrote a PdfService which abstracts away the handler library (i.e. IText). Why? Because we might stop using iText? Well, sure. But also it is just good practice to isolate the code which touches a specific library. If you upgrade iText and they break compatibility with the version you are using, it’s only broken in one place in your app because your app is loosely coupled with iText.

    Reply
  7. Scott Vachalek

    I think the only use for logging abstractions is for libraries that really need to log for some reason and want to play nice and put it in the application’s log. In that case (assuming for a moment there are valid instances of that case) you need some kind of API to wrap the 2-3 most common application logging APIs. There’s utterly no point for an application to use a logging abstraction, since 99% of a logging library is the API itself. The actual back end implementation is trivial and I have no idea why you’d want change it–it’s the front end that matters. As the song goes “if you choose not to decide you still have made a choice”.

    Reply
  8. martinus

    Logger abstraction is great when you use the library on different machines. On servers you can use log4j which is great. On memory + space limited devices you can switch to something else.

    Reply
  9. Paul

    Like all things, it depends.
    If you are just building a project, then yea, it doesn’t really matter.

    If you are building library code, then it matters more. When developing libraries, its useful for the consumers of you code to be able to make it work with whatever logging facility they happen to be using. It sucks to have a handful of libraries that each use a different logging mechanism. It is great when you make make them all use the same one (whatever that may be).

    Like all things, abstracting something away is no silver bullet, use the right thing in the right place.

    Reply
  10. Ivan Memruk

    WarpedJavaGuy: I’m not sure what you mean because the link you’ve given points to a description of a guy who’d successfully managed to direct all his logs to log4j without commons logging using the exact way that I had described earlier. From my experience, I can tell the same. jcl-over-slf4j is good for people like myself who don’t want to waste their life figuring out each particular case of commons-logging behaviour and configuration and prefer having one single log config per application.
    However, some frameworks use java.logging (e.g. facelets, as far as I remember), and I don’t have a solution to override them to use log4j.. 😦

    Reply
  11. WarpedJavaGuy

    Ok here goes..

    App servers like Tomcat and WebSphere, for example, ship with their own versions of JCL and are configured to use a particular logging implementation (say Log4j or Java Logging API). The problem occurs when you want to deploy a web application into the server that also uses its own JCL library and configures its own logging implementation. Now, because there are multiple classloaders in this environment and multiple JCL libraries and implementations, which JCL will the class loader that loaded your JCL consumer have visibility to? The server JCL or the WAR JCL? It all depends on how you configure your class loading mode at the EAR and WAR levels. If you use the PARENT_FIRST at the WAR level, then the classloader will first delegate the loading of classes to its parent classloader where it will find the server JCL. This is not what you want! If you use the PARENT_LAST at the WAR level, then the classloader will first attempt to load classes in your WAR where it will find your WAR JCL. This is what you want. BUT the problem is that it’s not all that simple. Other class libraries that are deployed at the EAR level could be using JCL too? What class loading mode are they using? If your JCL consumer references one of those classes and the class loader that loads those loads the server JCL then you will have a conflict between the two JCL versions. This is where things blow up. The app server is not able to separate the server/container and application classloaders in a way that does not cause conflicts with the two versions of the of JCL classes. It’s the paradox that is using JCL in a J2EE environment.

    Now if you were to replace the JCL in the WAR with the jcl-over-slf4j implementation you would still have the same problem. Like the JCL library being replaced, it too is just another version of JCL classes that will confuse all class loaders.

    Reply
  12. Pingback: The Dynamic Discovery Paradox « WarpedJavaGuy

  13. AngryA

    As a library vendor I have to ask myself if I’d like people who use complex environments to read and understand the complex class loading mechanism they have chosen to employ? Or do I want all users to configure 4 different logging mechanisms; all of which write to different files and don’t cooperate?

    This is a real issue you can’t just brush aside and say abstractions are pointless.

    Another + for JCL is the simplicity with which you can actually create stub of the Log interface. All the other options require either larger interfaces that are less intuitive (slf4j), or more gymnastics to wire up objects that don’t matter for what you want to test (jul, log4j).

    Reply
  14. AngryA

    To warped explanation of the classloader “problem” in a webcontainer,

    Pure FUD: You can’t half-ass bundle your webapps.

    Bundle the app and not the dependencies, leave it to the container and you have no problem and let you customers know that your installation model and it’s chaos. Have fun supporting that, I hope they chose to install the same version of your dependencies as you wanted.

    Pick some of your dependencies and hope everything works out for you & getting logging working is half your problem.
    I hope whatever random version the client had lying about was the same one you tested and built with.

    Package your webapp with exactly what it needs to run and you will no trouble.

    Reply
  15. WarpedJavaGuy

    It wasn’t my choice actually. It’s was an existing application for a client that I provided services to and these were my observations. Working on the project definitely did have it’s challenges, that’s for sure. Trying to get the logging to work was just one of them.

    Reply
  16. Peter Lawrey

    If you don’t care about logging abstract why use Log4j at all.
    You can just use plain old System.out/System.err, which I redirect to LOG.info and LOG.error anyway.
    We have been using common-logging/log4j with tomcat for about a year now and we haven’t seen any issues.

    Where I work we support System.out,err/commons-logging/log4j as different libraries use different logging techniques. (All them end up in Log4j for consistent configuration)

    Reply
  17. Rob Bygrave

    In regards your question, how to get juli to load a logging.properties file from the classpath.

    I believe you have to have code that you know will execute very early in your application(perferably the first thing), and have that call LogManager.getLogManager().readConfiguration(inputstream); where inputstream is for your classpath loggging.properties file.

    The problem is to know/have bit of code that does this either first thing (or early enough) in the bootup of your application. Not always easy… it would be nice if this was part of the default behaviour of LogManager.

    Reply
  18. Pingback: bonus enquete casino on net

  19. Jo

    The important thing about logging is that different libs might be using different logging facilities.
    That alone is reason enough to recommend commons logging. Not because it’s great or because it’s useful, but just because you don’t have to configure and integrate yet another logger for each lib you add.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s