Logging Facade or Logger in an Application for a newcomer - java

I am at the point for my little test-webapplication that I need some logging. I have no real experience in log4j nor java.util.logging and I was thinking if I should start right away with a logging facade (slf4j).
I was reading that a logging facade should be used for libraries that are shared (frameworks) which makes sense. But in case if a particular application I am not sure where to go. Would it be better to use log4j (or logback) directly due to performance? Or should I start with slf4j right away since I dont know the others anyway?
Thanks

Log4j, Java Logging are logging frameworks (A)
SLF4J, Commons-Logging are logging-facade frameworks (B)
www.slf4j.org/faq.html#when
Even when you use anything in list (B) above you still need to give it an underlying actual logger implementation (which is something from list A) for it to work properly.
So if you are doing a library which you will ship to someone (and you don't know which of the frameworks they will use from list A) THEN you should go for something in list B (SLF4J being the ideal)
If you are doing a standalone app then in all probability log4j (from list A) should solve your purpose.

For a standalone application I would start with Jakarta Commons Logging together with log4j.

I don't recommand java.util.logging, as finding a configuration mistake with it is a nightmare. The best choices are:
log4j for backend
commons-logging (more popular) or slf4j (more recent) for frontend
UPDATE: this recent blog entry can help you choose decent / recent / usable logging frontend and backend

SLF4J was created as an improvement to log4j, issues addressed include performance and, i think the most beneficial, the ability to plug in a logging framework at deployment time.
I suggest you start with the first, log4j, its very simple and will make understanding SJF4J easier as well.

Related

Apache Commons Logging implementation differences

I will try to use the Apache Commons Logging to logs in my system. I need some simple, just to keep up on the information and errors, nothing too complex.
I saw that there a lot of implementations there (SimpleLog, AvalonLog, etc.) Someone can explain me the most appropriate or the most complete/full of resources?
Actually I don't know which one to use.
Commons-logging is not a simple logging mechanism. It's a method of allow you to write a library that works regardless of the logging mechanism chosen by someone who incorporates your library.
If you want a simple logging mechanism, just use java.util.logging directly. If you want an even simpler API, use slf4j and then use their 'simple' backend.
You don't need commons-logging unless you have to fit into other people's environments.

What is the issue with the runtime discovery algorithm of Apache Commons Logging

Dave Syer (SpringSource) writes in his blog:
Unfortunately, the worst thing about commons-logging, and what has made it unpopular with new tools, is also the runtime discovery algorithm.
Why? What is the issue with its runtime discovery algorithm? Performance?
Why? What is the issue with its runtime discovery algorithm? Performance?
No, it's not performance, it's classloader pain. JCL discovery process relies on classloader hacks to find the logging framework at runtime but this mechanism leads to numerous problems including unexpected behavior, hard to debug classloading problems resulting in increased complexity. This is nicely captured by Ceki (the author of Log4J, SLF4J and Logback) in Think again before adopting the commons-logging API (which also mentions memory leaks problems observed with JCL).
And this is why SLF4J, which uses static bindings, has been created.
Ceki being the author of SLF4J, you might think his articles are biased but, believe me, they are not and he is providing lots of references (evidences) to prove his point.
To sum up:
Yes, JCL is known to be broken, better stay away from it.
If you want to use a logging facade (not all projects need that), use SLF4J.
SLF4J provides a JCL-to-SLF4J bridge for frameworks still using JCL like Spring :(
I find Logback, Log4J's successor, to be a superior logging implementation.
Logback natively implements the SLF4J API. This means that if you are using Logback, you are actually using the SLF4J API.
See also
Commons Logging was my fault
Think again before adopting the commons-logging API
SLF4J Vs JCL / Dynamic Binding Vs Static Binding
Commons logging is a light weight logging facade which is placed on top of the heavy weight logging API be that log4j, java.util.logging or another supported logging API.
The discovery algorithm is what commons logging uses to determine what logging API you use at runtime so it can direct log calls through its API to the underlying logging API. The benefit of this is that if you wanted to create a library that does logging, you do not want to tie down users of your library to any particular heavy weight logging system. Callers of your code can configure logging via log4j, java.util.logging etc. and commons logging will forward to that API at runtime.
Common gripes for commons logging:
Even though you don't use it, a library you depend on might so you have to include it in your classpath anyway.
Runs the discovery algorithm for each classloader you want to do logging in, which can produce unwanted results so make sure you put commons-logging.jar in the right classloader.
Greater complexity than the underlying logging framework.
Less features that underlying logging framework.
A perceived greater complexity as well as unpredictability in complex classpath hierarchies without any perceived benefits make users of commons-logging agitated. Given also that this choice may be forced on you does not make users sympathetic. See this article for a compelling argument against using commons-logging.
I can't speak about the "believed unpopular" aspect, I can only speak for myself:
Commons Logging is a facade over top of whatever your "real" logging framework may be: Log4j, Logback or whatever.
The idea of a logging facade is that your app gains the flexibility to decide at runtime which logging implementation it wants to work with. The facades are clever enough to find logging implementations at runtime.
My older Java apps use Log4j, directly. Works fine, I see no need to change them. My newer Java apps will probably use Logback. I think the ability to dynamically choose a logging framework is something none of my apps will ever need. Of course, other peoples' mileage may vary.
EDIT: Looks like I was wrong about the rationale for Commons Logging. The links given by #Pascal Thivent, especially the first one, explain this far better.
Commons Logging contains logic to determine at runtime whether to use log4j or java.util.logging.*.
That code used to be seriously broken, essentially only working with JUL.
Based on the experiences with this, slf4j was written which uses static binding (or used to, Im not sure with version 1.6) to choose the appropriate framework to use of log4j, JUL or the log4j fork logback (and more), and it includes a bridge to allow existing Commons Logging code to use slf4j transparently.
If you can, then go for slf4j.

Difference in using java.util.logging and Log4j Loggers

I am developing a java application for which i have to use a logging mechanism. And now i am confused to choose either java libraries logger or to go for Log4j logger.
So i want to know when i can go for java logger
and when i can go for log4j logger.
I'd suggest you go with SLF4J instead to decouple your application from specific logging frameworks. It has adapters for various popular logging frameworks such as Jakarta Logging, JDK1.4 logging, log4j etc. making it a good abstraction for logging needs.
Logger class was not part of jdk earlier on, so several library implementations sprung up. The Log4j library has one of the most comprehensive set of logging utilities (Formatters, Appenders etc). However, for most developers this would be an overkill and the simple java.util.Logger would suffice.
I personally use a custom wrapper over my logger implementation. This enables me to define custom calls to carry out functional logging/auditing.
There are the Apache Commoms Logging project and SLF4J, either of which abstracts the underlying logging library.
In practice I tend to use Log4J over the built in logging classes. Mainly because Log4J can be configured per web-app in an application server, whereas JDK logging is configured per JVM.
The approach I would currently recommend is to use SLF4J as the logging API. You can then pick your logging framework depending on your needs as you discover them.
I did a writeup on what I consider to be best practice in getting started with SLF4J and a simple "log to System.out" which is currently placed at. http://runjva.appspot.com/logging101/index.html
Hopefully it is helpful.
I find Log4j more flexible when it comes to tweaking the logging cfg without re-compiling code in production environment.

Logging using SL4J, Jakarta Commons logging, log4j for third party libraries and my own code

I have some questions about logging, more specifically about setting it up and making sure it works.
The project I'm doing will use Wicket, Spring and Hibernate. I know that Wicket and Hibernate uses Simple Logging Facade for Java (SL4J) and that Spring is using the logging component from Apache Commons.
Will they co-exist happily?
I thought I would use log4j together with both SL4J and the logging component from Apache commons, do you think that's a good idea?
Can I set up them all to output logging data into a common file?
Or should I use separate files?
Or should I store the logging messages in the database? (I'd rather not, as I find grepping etc on text files quite convenient.)
For Spring I guess I need some kind of configuration file for the Apache Commons logging component as well where I direct it to use log4j?
When I've set these up I guess to see that everything works I set the logging level to INFO as it's fairly certain that all three of the frameworks output some information in that mode? Or is there an even better way to make sure?
And my last question. In the project I'm starting, do you recommend that I use SL4J for my own logging purposes? (I thought I would use log4j directly, but that was before I learned a little bit more about logging and a lot of respectable libraries seem to choose the path of a bridge/facade for their logging needs. And if it gets us flexibility without added cost there's no reason not to do it that way.)
I'm looking forward to hearing more from you about how you are doing your logging. It's a new area for me which I'm eager to improve myself in.
Well SLF4J is just a facade, like commons logging, which means they still need something else to work. They permit library authors to not force users into having multiple logging library and configuration. Log4j and logback are regular logging libs.
See here for more info.
SLF4J has a commons logging bridge that you can use to replace the commons logging library. I think the schema there explain the situation very well.
Now, you just need to use slf4j-logj12.jar to have commons logging and slf4j use log4j (or anything else you chose; btw, logback doesn't need an additional library to be used with slf4j) as a backing engine.
You application will thus have
jcl104-over-slf4j.jar (to bridge jakarta commons logging to slf4j)
slf4j.jar (for hibernate and others to use slf4j)
slf4j-logj12.jar (for slf4j to use log4j as a backend)
log4j.jar (for your application to use. all config will also be done here)
Here is how to redirect everything to SLF4J:
remove commons-logging.jar from your classpath. If you are using Maven and have trouble getting rid of commons-logging, see this.
put jcl-over-slf4j.jar in your classpath (it comes in the SLF4J distribution). This is a drop-in replacement that mimics JCL's classes, but calls SLF4J internally. This will take care of Spring, and any other framework that uses JCL.
Connect SLF4J to your favorite backend (Log4J, Logback...) by putting slf4j-xxx.jar in the classpath. Configure the backend to log all categories to one file, and you're done.
As for using SLF4J in your application, it is not strictly necessary. Libraries like JCL and SLF4J were originally designed for people who write libraries and do no want to lock their clients into a particular logging framework.
PS: by the way, JCL = Jakarta Commons Logging

Are there technical reasons to prefer using logback instead of log4j?

Should new projects use logback instead of log4j as a logging framework ?
Or with other words :'Is logback better than log4j (leaving the SLF4J-'feature' of logback beside)?'
You should use SLF4J+Logback for logging.
It provides neat features like parametrized messages and (in contrast to commons-logging) a Mapped Diagnostic Context (MDC, javadoc, documentation).
Using SLF4J makes the logging backend exchangeable in a quite elegant way.
Additionally, SLF4J supports bridging of other logging frameworks to the actual SLF4J implementation you'll be using so logging events from third party software will show up in your unified logs - with the exception of java.util.logging that can't be bridged the same way that other logging frameworks are.
Bridging jul is explained in the javadocs of SLF4JBridgeHandler.
I've had a very good experience using the SLF4J+Logback combination in several projects and LOG4J development has pretty much stalled.
SLF4J has the following remaining downsides:
It does not support varargs to stay compatible with Java < 1.5
It does not support using both parametrized message and an exception at the same time.
It does not contain support for a Nested Diagnostic Context (NDC, javadoc) which LOG4J has.
The author (of both Logback and Log4j) has a list of reasons to change at http://logback.qos.ch/reasonsToSwitch.html.
Here are a few that stuck out at me;
Faster implementation
Based on our previous work on log4j,
logback internals have been
re-written to perform about ten times
faster on certain critical execution
paths. Not only are logback
components faster, they have a
smaller memory footprint as well.
Automatic reloading of configuration
files
Logback-classic can automatically
reload its configuration file upon
modification. The scanning process is
both fast and safe as it does not
involve the creation of a separate
thread for scanning. This technical
subtlety ensures that logback plays
well within application servers and
more generally within the JEE
environment.
Stack traces with packaging data
When logback prints an exception, the
stack trace will include packaging
data. Here is a sample stack trace
generated by the logback-demo
web-application.
14:28:48.835 [btpool0-7] INFO
c.q.l.demo.prime.PrimeAction - 99 is
not a valid value
java.lang.Exception: 99 is invalid
at
ch.qos.logback.demo.prime.PrimeAction.execute(PrimeAction.java:28)
[classes/:na] at
org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)
[struts-1.2.9.jar:1.2.9] at
org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
[struts-1.2.9.jar:1.2.9] at
org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
[struts-1.2.9.jar:1.2.9] at
javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
[servlet-api-2.5-6.1.12.jar:6.1.12]
at
org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502)
[jetty-6.1.12.jar:6.1.12] at
ch.qos.logback.demo.UserServletFilter.doFilter(UserServletFilter.java:44)
[classes/:na] at
org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)
[jetty-6.1.12.jar:6.1.12] at
org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:361)
[jetty-6.1.12.jar:6.1.12] at
org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
[jetty-6.1.12.jar:6.1.12] at
org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
[jetty-6.1.12.jar:6.1.12]
From the above, you can recognize
that the application is using Struts
version 1.2.9 and was deployed under
jetty version 6.1.12. Thus, stack
traces will quickly inform the reader
about the classes invervening in the
exception but also the package and
package versions they belong to. When
your customers send you a stack
trace, as a developer you will no
longer need to ask them to send you
information about the versions of
packages they are using. The
information will be part of the stack
trace. See "%xThrowable" conversion
word for details.
This feature can be quite helpful to
the point that some users mistakenly
consider it a feature of their IDE.
Automatic removal of old log archives
By setting the maxHistory property of
TimeBasedRollingPolicy or
SizeAndTimeBasedFNATP, you can
control the maximum number of
archived files. If your rolling
policy calls for monthly rollover and
you wish to keep one year's worth of
logs, simply set the maxHistory
property to 12. Archived log files
older than 12 months will be
automatically removed.
There may be a bias there, but the same guy did write both frameworks and if he is saying use Logback over Log4j he's probably worth listening to.
I would use slf4j for logging in all cases. This allow you to choose which actual logging backend you want to use, at deploy time instead of code time.
This has proven to be very valuable to me. It allows me to use log4j in old JVM's, and logback in 1.5+ JVM's, and also java.util.logging if needed.
Logback more Java EE aware:
in general (from code to documentation) it’s keeping in mind containers – how multiple apps coexist, how class loaders implemented etc. Contexts for loggers, JNDI, JMX configuration included etc.
from developer prospective almost same, Logback adds
Parameterized logging (no need to use if(logger.isDebugEnabled()) to avoid string concatenation overhead )
Log4j – only giant plus is old JVM support, small (IMO)
NDC (Logback only MDC), some extensions. For example I wrote extension for configureAndWatch for Log4j, no such thing for Logback
the original log4j and logback were designed and implemented by the same guy.
several open source tools have used SLF4J. I don't see any significant deficiencies in this tool. So unless you have a lot extensions to log4j in your codebase, I would go ahead with logback.
I would think that your decision should come down to the same one it would if you were deciding between using log4j or Jakarta Commons Logging - are you developing a library which will be included in other applications? If so, then it doesn't seem fair to force users of your library to also use your logging library of choice.
If the answer is no, I would just go with what is simpler to add and what you are more comfortable with. Sounds like logback is just as extensible and reliable as log4j, so if you're comfortable using it, go ahead.
I'm not familiar with SLF4J, and I've only taken a brief look at logback, but two things come to mind.
First, why are you excluding a tool from examination? I think it's important to keep an open mind and examine all possibilities to choose the best one.
Second, I think that in some projects one tool is a better than another tool, and the opposite might be true in a different project. I don't think that one tool is always better than another tool. There is, after all, no silver bullet.
To answer your question - Yes and no. It depends on the project, and how familiar the team is with one tool. I wouldn't say "don't use log4j" if the entire team is very comfortable with it, it meets all the needs, and logback doesn't offer anything that we need to complete the task.

Categories