As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Why one would use one of the following packages instead of the other?
Java Logging
Commons Logging
Log4j
SLF4j
Logback
In chronological order of api apperance (as far as I know):
Log4j because most everybody uses it (in my experience)
Commons Logging because open source projects use it (so they can integrate with whatever logging framework is used in the integrated solution); especially valid if you're an API/Framework/OSS and you rely on other packages that use Commons Logging.
Commons Logging because you don't want to "lock down" to a particular logging framework (so instead you lock down to what Commons Logging gives you instead) - I don't think it is sensible to decide using this point as the reason.
Java logging because you don't want to add in an extra jar.
SLF4j because it's newer than Commons Logging and provides parameterized logging:
logger.debug("The entry is {}.", entry);
//which expands effectively to
if (logger.isDebugEnabled()){
// Note that it's actually *more* efficient than this - see Huxi's comment below...
logger.debug("The entry is " + entry + ".");
}
Logback because it's newer than log4j and again, supports parameterized logging, as it implements SLF4j directly
SLF4j/Logback because it's written by the same guy who did log4j, so he's made it better (according to Ken G - thanks. It seems to fit when looking at their earlier news posts)
SLF4j because they also publish a log4j adapter so you don't have to "switch out" log4j in older code - just make log4j.properties use SLF4j and it's configuration
I find logging in Java to be confusing, inconsistent, poorly documented, and especially haphazard. Moreover, there is a huge amount of similarity between these logging frameworks resulting in duplication of effort, and confusion as to what logging environment you are actually in. In particular, if you are working in a serious Java web application stack, you are often in multiple logging environments at one time; (e.g hibernate may use log4j, and tomcat java.util.logging). Apache commons is meant to bridge different logging frameworks, but really just adds more complexity. If you do not know this ahead of time, it is utterly bewildering. Why are my log messages not printing out to the console, etc.? Ohh because I am looking at the Tomcat logs, and not log4j. Adding yet another layer of complexity, the application server may have global logging configurations that may not recognize local configurations for a particular web application. Lastly, all these logging frameworks are WAY TOO COMPLICATED. Logging in Java has been a disorganized mess leaving developers like me frustrated and confused.
Early versions of Java did not have a built-in logging framework leading to this scenario.
There's one important point that wasn't mentioned before:
SLF4J (and both Logback and LOG4J as the logging backend) have support for a so called Mapped Diagnostic Context (MDC, see javadoc and documentation).
This is essentially a thread-local Map<String,String> which you can use to add additional context information to your logging event. The current state of the MDC is attached to every event.
This can be incredibly useful if you put stuff like the username and the URL of the request (in case of a webapp) into it. This can be done automatically using a filter, for example.
See also answers to the question What are the best practices to log an error?, especially:
There are some potential
classloading issues with Commons
Logging.
Log4J and SLF4J were developed by
the same person, learning from
issues found in practice with Log4J.
In our company project we use LOG4j and it is very easy to use like Stephen showed in his example.
We also have written our own pattern classes for LOG4j so you can create your own output file schemas. You can describe how your log file should look like. It is possible to enhance the original log4j classes.
All LOG4j properties you can change in a log4j.properties file, so you can use different files for different projects.
Java logging is not my favorit, but this could be because i use log4j from the beginning.
The Commons Logging overview gives the reason for its existence: logging from library code, when you have no control over the underlying logging framework. Very important for the various Apache projects, which will be linked into outside applications. Perhaps not so important for internal IT projects, where you have complete control.
That said, I write to Commons Logging, as do many of the other developers I know. The reason is to minimize mental baggage: you can change projects or jobs, and not have to learn a new framework (provided the new job/project also uses CL, and/or you can convince them to move to it).
Also, there is some value to creating your own wrappers around whatever framework you use. As described here, I like to use a LogWrapper object to provide custom stringification (important), and minimize the visual clutter of logging statements (less important).
Generally I would default to using Log4J.
I would use Java Logging if I didn't mind a dependency on Java 1.4 but I would still use Log4J in preference.
I would use Commons Logging if I was enhancing something that already used it.
I would suggest creating a thin logging facade that can write to any of the logging frameworks, at which point the choice of backing engine become pretty much a moot point.
Related
Digging into some Java logging stuff, and question about slf4j. It seems awfully convenient, always doing the logging same way in .java files, worrying only about logger name, then doing all logging configuration by having right .jar and .properties/.xml files.
What are the reasons to use or not to use slf4j by default in any project?
In this particular case, log4j will actually doing the logging (some to file, some to stdout, some to database), and it is a maven project.
I'm hoping for simple "yeah, go for it" or "no, using slf4j is asking for trouble X" from somebody with experience.
We have been logging over the SLF4J API for 1.5 years now. Before that we used log4j directly. Now we use jboss.logging, with a logback intermezzo and had to change zero lines in our code for all the framework changing.
So, go for it ;)
Definitely use slf4j. It's the standard common logging interface of today and it finally does it right regarding the plugging in of actual logging implementations. Logback as the implementation is highly recommended, it is the successor of log4j, done by the same guy who quit log4j to it from the start, but straightening out the issues that couldn't be straightened out in log4j.
Ok, I actually ended up not using slf4j, but instead using log4j directly, because slf4j just kept on using JDK14LoggerAdapter instead of Log4jLoggerAdapter or LogBack, and I got fed up trying to get it to work by tweaking dependencies...
The project in question is Jenkins plugin built with Maven2, that may have been the reason of complications. It really did not work by "just put these dependencies to .pom".
So, to answer my own question, a reason to not use slf4j is: less moving parts, less dependencies, less manuals and docs to read through, less questions to ask at SO/mailing lists.
I want to log information to a file and want to know is there any advantage in using the Java Logger class versus my own personal method of logging?
I know using a logger I just add my own FileHandler to the logger. My personal method is just using a FileOutputStream.
Honestly your logger may be as good, it's pretty easy to put in log levels, filtering, etc.
The problem is when you start to put together code from 10 different groups each with their own logging. Some use System.out, some use some custom logger, some use log4j, ...
How do you parse or redirect the output? How do you filter all that output to just show your messages (For instance, filtering options in log4j won't prevent messages being sent straight to System.out).
It's a pretty big bulk change depending on which system you are moving from/to. Better just to use one very common one from the beginning and hope that it's the one everybody else on the project chooses.
The real question is: why would you bother writing your own logger when there are already existing libraries for doing that? Does your logger do something that the others don't? I kind of doubt it.
Standardization is another big issue - see Bill K's answer.
For most scenarios, a standard logging framework is the way to go. They are pretty flexible. But using your own implementation can also be a valid option, specially if we are not speaking of traditional logging (global debugging, problems, warning messages) but about specific informational meesages or accounting.
Among other factors, bear in mind that the standarization of logging allows third party libraries to cooperate. For example, if you have a standard web application using (say) Hibernate, and you have configured a standard Java logging lib, then you can not only log from your own code but also tell Hibernate to log debugging info to your log files (not necessarily the same files). That is very useful - almost a must.
If you code your own logging library with a plain FileOutputStream, you must decide -among other things- if you are going to keep the file opened, or reopen-append-close in each write - and you must take of synchronization and related issues. Nothing terribly complicated, though.
The logger gives to ability to define different levels of importance of the logged messages and the ability to use different sink for the output - the console, a file, etc.
Also it's easy to enable or disable only some type of message when using a logger - for example you don't want to see every debug message in production.
A logging framework allows you specify logging levels (e.g. log only critical messages, log only debug messages etc.). It also allows you to log to multiple destinations (e.g. to a file, to syslog etc.) and you can do this even after your application is fully built by just changing a config file and not changing any code. It can also format your logs easily depending on various parameters.
There are numerous other advantages since proper logging is a rather involved problem and these packages have been written to solve them. I think the important question, why would you not use them?
Well I would always prefer tested thing and approved by community over something which still need a lot of test. Logger allows you many things which will consume you some time to implement and to test the robustness of your solution. A big plus will be the know-how of the next person who will do something with your code, in case it will be your logger, normally it would take more time to learn how its working out, since there is much more examples and documentation for java.util.logger.
Like all others mention, there are more advantages to using a more common logging system over writing your own. To be honest, the Java util logging api is not nearly as extensive and configurable as other libraries you might find out there on the internet.
Bare in mind that rolling your own always has the disadvantage of being less tested and therefore more prone to break or skip some potentially crucial messages.
Personally I prefer using SLF4J since it allows me to plug in adapters for more commonly used logging frameworks and then let's me pick my own actual logging implementation, this solves most of the problems with different library writers preferring different logging frameworks. And if you consider yourself up for the task you could writer an implementation for SLF4J yourself ;)
We are developing a web-based application in Java using the Spring framework. We are wondering which Logging system would be the most appropriate for it, whether Log4j or JUL (java.util.Logging), which is integrated with jdk. As far as I'm concerned, the former is more popular among developers and offers higher customization options, but I'm not sure which is simpler to adapt with spring.
any help will be appreciated.
thanks!
Before you start with log4j, look at logback. Log4j shouldn't be used for new projects anymore. If you have legacy code that needs any logging framework, use slf4j to make the old code talk to logback (or log4j if you must).
The main reasons you should not use JUL is that it implements the bare minimum that you need for logging, the configuration is hard at best and, if you use any component that doesn't use it, you'll have to deal with two logging frameworks.
Regardless of which logging framework you use in your own code, as far as I can remember, Spring has a hard dependency on commons-logging. You can still use whatever you like for your own logging (I'd recommend SLF4J as your facade, with logback as your implementation), but Spring internally needs commons-logging. Whether you want to depend on multiple frameworks is your choice; it shouldn't prove problematic.
Spring uses commons logging, which is a log abstraction facility but has issues that sl4j doesn't have. Hibernate moved to slf4j - I would like to see spring do the same, but I don't think they have any plans in this regard.
So as long as your log abstraction facility (use slf4j) logs to the same logging framework as you've configured commons logging in spring, then you're good. One log configuration for both. You might find an adapter for logback for commons and slf4j.
Since the other responses didn't actually answer your question, I thought I'd have a stab at it.
Firstly, java.util.logging is horrible. It's a pain to use, and a pain to configure. Log4J is nicer on both counts. However, you should pick whichever one you're most comfortable with. Spring uses commons-logging, which in turn will use either log4j (if found on the classpath) or java.util.logging otherwise. In otherwords, if your application already has log4j present, then Spring will effectively use that, and so should you. If log4j is not already present, then either use java.util.logging (if you choose to), or add log4j to your classpath and use that.
How does The JDK's Logger compare to Apache log4j?
Which one is better for new projects that target Java 6? How do they compare in terms of flexibility and configurability?
To my mind the only thing the JDK Logger has going for it is that it is part of the JDK, so it doesn't add an external dependency. If the choice is only between those two, I'd go with Log4j. It still has better support in terms of appenders, the number of people who know it (in my anecdotal observations), and a better API (that is subjective as well).
Starting a project today, the most tempting thing to do is go with slf4j and deffer the decision - you can always plug in a different framework underneath slf4j by just changing the classpath.
That being said there are other options (such as Log5j) that take advantage of the latest Java language features. I'd recommend taking a long look Logback (from one of the main programmers of Log4j, as is slf4j).
I've never used the direct JDK logger, but for a new project I'd highly reccomend Logback,
designed as a successor for log4j. Some of the very nice things you can do with it:
printf style parameter building, no more messy concatenating strings protected by if logger.isDebugEnabled() guards.
go from
if (log.isDebugEnabled())
{
log.warn (i + "many ints,"+ l+"many longs");
}
to
log.debug("{} many ints, {} many longs", i, l);
very flexible config, including configurations that will print traces. The config is xml, but their site includes a utility that will generate an xml config from your log4j config to get you started.
Downside - lots of packages require log4j anyway, since it's so common, so your project may need to include 2 logging packages.
For a new project I would strongly recommend the slf4j project which provides generic frontend to several logger frameworks.
The {}-syntax described by Steve B is present in slf4j too (same author) so you get all the benefits regardless of backend, and STILL get the backend independency. Also a log4j bridge is available so existing code transparently can use slf4j. It is really nice.
For actual backend, logback is nice but you may already have invested in log4j - this is easily leveragable.
I would recommend the JDK logging API. I have used it for many years, without any problem whatsoever. It's part of the JDK, so no extra jar is required. The distinctions between log4j and JDK logging are small, and, in my opinion, don't justify the use of log4j.
Standard API vs log4j
A common question asked by Java developers is:
Why we should use log4j logging framework when Java provides an API
for logging. The java API can be accessed by (java.util.logging)?
Log4j has following advantages over standard logging API:
log4j provides robust logging
log4j has more features available than standard logging API
configuring and using log4j is easier
log4j also has a much more robust formatting system
many add-on programs and handlers are available for log4j
I struggled with this question several times; with jdk7 and jdk8; java logging super fast and slick, but only thing we need to put programmer hat while configuring.
To log to multiple file destiantions, we neeed to create signare classes extending FielHandler and use them in properties file to configure, this kind intricacies appears time consuming but once you get hang efficiency and reliability are awesome.
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?
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.
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.
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.
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.
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)
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.