views:

651

answers:

7

I'm currently looking at upgrading the logging mechanism in a medium-to-large-sized Java codebase. Messages are currently logged using static methods on a Debug class, and I have recommended switching from this to something like SLF4J or commons-logging.

The application architect prefers that I encapsulate the dependency on SLF4J (possibly by wrapping it up in the aforementioned Debug class). This will make it easier to change the logging implementation in the future.

This seems like overkill to me, as SLF4J is already abstracting the concrete logging implementation.

Is it worth wrapping a 3rd-party logging abstraction like SLF4J in another home-grown abstraction?

+12  A: 

I entirely agree with you: wrappers of wrappers of wrappers are getting out of hand. I suspect that architect doesn't realize how SLF4J in particular can easily wrap any other logging system, so that "changing implementation" is perfectly feasible without yet another layer of wrappage.

Alex Martelli
Indeed. I can only foresee 2 possible reasons why we'd ever need to switch from SLF4J: either SLF4J becomes entirely extinct, or someone invents an entirely new way of logging that is completely different to the way everyone does it now. Both seem equally unlikely :)
harto
+1 on @harto's comment because it's so perfect a soundbyte!-)
Alex Martelli
A: 

If you're thinking of switching Logging frameworks in the future, it may be worthwhile to add an extra layer to where you can switch out the logger. Otherwise, if they provide everything that you will possibly need(using your crystal ball, of course) then it is probably ok to have a hard dependency on that framework.

If your current setup allows flexibility to change, you don't need a wrapper.

Kekoa
point is, SLF4J is _already_ designed to wrap "any possible logging system" (they _are_ ambitious, but also quite skilled...), and already provides several wrappers as well as native implementations.
Alex Martelli
then you're good to go
Kekoa
SLF4J is designed to wrap the currently popular (existing) logging frameworks. SLF4J does not and cannot make claims about future logging frameworks.
Ceki
There's a good idea. Add another layer.
stu
+4  A: 

Explain to your Architecture Astronaut that slf4j already can act as a wrapper for other logging implementations, like log4j. So if you need to use some other logger in the future and there is no adapter for slf4j, you can write it when the need arises, but it will just be the adapter, instead of writing a whole logging framework that will just wrap some other logging framework and you need to design your framework for that and write your own adapter.

Chochos
+3  A: 

I would prefer to wrap it, but not for the stated reason. If the concern is the ability to swap out for another framework, use java.util.logging or SLF (java.util.logging isn't as easy to use as a wrapper, but it is quite doable), and swap away. The reason to use (yet another) wrapper is to codify in code the appropriate way of logging. Generally an application wants a subset, such as all system errors come with an exception, or have specific guidance about when to use the standard logging levels. Those decisions can be encapsulated in a few methods creating more consistent logging decisions over a large code base.

If, however, the motivation is just to make it possible to swap out implementations, don't reinvent the wheel. SLF is perfect for the job, just use it.

There is one exception to this. If your code is meant to be deployed into many possible app servers seemlessly, you do have to make sure that your logging choice doesn't risk conflicting with potentially older or newer versions of whatever the framework is using.

Yishai
Good point about the appropriate way of logging. It's certainly going to be important to ensure that logging is done in a consistent way. Regarding the deployment consideration, the core library is deployed not only as part of our web apps, but also to the desktop. However, we're generally only using Tomcat 6, so I don't think that's a concern.
harto
Adding a proprietary logging wrapper will likely destroy the call location feature of the logging backend. Beside that, it's one more module that you have to support (debug, bugfix) while a sufficiently used third-party module is mostly (in a relative way ;)) bug-free already.
Huxi
Mostly, in a relative way? Hey, don't scare our users! :-)
Ceki
SLF4J makes extremely serious efforts to preserve compatibility. Actually, *all* of the compatibility issues encountered recently in SLF4J have to do with code responsible for compatibility management. Keep in mind that any wrapper that you might write on your own, will have issues as well.
Ceki
No software is bug-free, you just have to look harder for them :D
Huxi
The wrapper won't conflict with a framework you happen to deploy on, so you could swap the framework with a non conflicting one and only affect the wrapper. Regarding the call location feature, it depends on how you implement it and the framework involved. We were able to do it with log4j without issues.
Yishai
+1  A: 

The problem with every wrapper is the decision of how you'll actually wrap and which functionality you'll provide:

  • commons.logging is providing a minimal set of logging functionality, hiding away additional functionality that the underlying framework might provide. You won't get advanced features like parameterized logging or the MDC.
  • SLF4J works the other way around. It handles advanced features like parameterized logging by implementing them on top of frameworks that aren't implementing them natively. This is the better way, IMHO.

I don't know your current Debug class but I guess it's pretty basic.

You probably won't have features like

  • the location of the logging message, i.e. name of the source file + line number
  • different logging levels
  • the ability to selectively set the level of different loggers, i.e. you don't have one logger per class, having the ability to set that logger to a certain level of interest, e.g. INFO, WARN. This is pretty crucial.

If your Debug class is pretty basic this is actually very nice for you :)

It means that you are likely able to switch over to SLF4J by performing a global search & destr... err... replace.

Make backups, though... ;)

See also Should new projects use logback instead of log4j?, What’s Up with Logging in Java?, Which log4j facade to choose?, Find a way in the java logging frameworks scene. and Do you find java.util.logging sufficient?. (Spoiler: You shouldn't use java.util.logging, pretty please)

Huxi
+5  A: 

I guess the motivation behind the architect's desire to wrap the wrapper (i.e. SLF4J), is to isolate your application from SLF4J. Clearly, invoking the SLF4J API from within your application creates a dependency on SLF4J. However, it is equally legitimate to want to apply the isolation principle repeatedly as discussed below. It reminds me of Richard Dawkins' question: If God created the universe, then who created God?

Indeed, you could also apply the isolation principle on the wrapper that wraps SLF4J. The cause of isolation would be ill served if the SLF4J-wrapper was somehow inferior to SLF4J. Although possible, it is rather rare for a wrapper to equal or surpass the original. SWT can be cited as a noteworthy counter-example. However, SWT is a sizable project with a significant cost. More to the point, an SLF4J-wrapper by definition depends on SLF4J. It is bound to have the same general API. If in the future a new and significantly different logging API comes along, code that uses the wrapper will be equally difficult to migrate to the new API as code that used SLF4J directly. Thus, the wrapper is not likely to future-proof your code, but to make it heavier by adding an additional indirection.

In short, even if you didn't have anything better to do, you shouldn't waste your time wrapping SLF4J because the added value of your wrapper is guaranteed to be near zero.

The topic is also broached in an SLF4J FAQ entry.

Ceki
A: 

"Is it worth wrapping a logging framework in an additional layer?"

No.

Dave