I have this 3rd party library that has:
slf4j-api-1.5.5.jar
slf4j-jdk14-1.5.5.jar
jcl-over-slf4j-1.5.5.jar
I want to write some tests against this library and see its log output, and I don't want to add any more logging libraries (no log4j or anything else).
I understand that SLF4J and Common Logging are both logging abstractions so I probably need to write my own simple concrete logger (or maybe not, since jcl-over-slf4j includes org.apache.commons.logging.impl.SimpleLog?). If so, what interfaces should I implement, and more importantly, how do I set up SL4J/Common Logging to use my logger in my test? I read in the SLF4J docs that I have to modify the StaticLoggerBinder class... does that really mean that I actually have to download SLF4J sources, modify the class and recompile it?
We use SLF4J. It's very useful but several of the jars have confusing names and it's not real clear starting out to know which ones are incompatible.
SLF4J is the API you use for logging in your code (e.g. log.info("blah"). However, SLF4J has no configuration aspect to it. At runtime you add exactly one jar to the classpath that binds the API to the 'real' logging subsystem. If you want to use Log4J, add slf4j-log4j.jar or the StaticBinder jar for Simple or JDK, or Logback. You configure any of these logging implementations as you normally would without SLF4J.
There are several SLF4J modules available to redirect existing logging statements written using the APIs of Log4J, Apache Commons Logging, and java.util.logging to SLF4J. This allows you to setup a single logging configuration for all these disperate implementations. (This is very useful to avoid configuring both, say, Log4J and JUL if you have libraries that bind directly to any legacy logging framework.)
The SLF4J legacy page explains these concepts in depth. Heck, there is even a module to redirect Sysout.out/err to SFL4J.
To more directly answer your question: sure you can write your own logging implementation to go under SLF4J; but the only reason to do so is because you are already locked into some homegrown craptastic logging framework.
If you want to keep it simple, use the built-in (as of jdk 1.4) logger
https://docs.oracle.com/en/java/javase/19/docs/api/java.logging/java/util/logging/Logger.html
the jdk binding jar comes with slf4j. you want to make sure the jar is deployed to your webapp WEB-INF/lib dir or just in your classpath otherwise. See (slf4j.org/faq.html#where_is_binding) and this (slf4j.org/faq.html) for more information.
the jar you want to add to your classpath is slf4j-jdk14.jar. Note that the jdk logger is already available, this jar is the link between the slf4j interfaces and the chosen logger implementation. the jdk logging binding jar comes with the slf4j distribution. this should do it for you.
Your question leds me to believe that you have not read the the SLF4J user manual. It's a very short document. If after reading the document you still have the same question, then the document fails its purpose and needs to be clarified.
Anyways, you don't need to implement your own Logger class. Just use slf4j-simple which ships with SLF4J.
Related
So I have a large application using log4j. We are developing internally our own log implementation, that has nothing to do with log4j, but it conforms to the log4j API for logging. Therefore we just want to somehow swap log4j for our log implementation without changing anything in our code, in other words, it will continue to use the log4j API with our log implementation under-the-hood.
Has anyone done that or know how to go about doing that?
It would be easy if I was using SLF4J, but unfortunately I'm not.
Your best bet would be to write your custom logging framework as an slf4j implementation.
Then, remove log4j from the class path and drop in the log4j-over-slf4j bridge instead.
http://www.slf4j.org/legacy.html
The log4j-over-slf4j bridge will take any calls made to log4j and redirect through slf4j to whichever slf4j subsystem you're using on your classpath, which would in this case be your custom library.
Suppose there is an application, which uses log4j directly, i. e. without slf4j or any other wrapper. Now I would like to replace the log4j with logback. Should I use slf4j (or any other wrapper)? What is considered "good practice"?
You surely should use slf4j API, if you later decide to go back to log4j or something else you will only need to change slf4j bridge, and your application logging code will work without changes. Besides, if you visit http://www.slf4j.org/ you will see that slf4j considers Logback as its native implementation, Logback actually natively implements the SLF4J API.
As mentioned by Evgeniy Dorofeev, logback natively implements the slf4j-api. This means that invocation of a logback logger via the slf4j-api, that is via an instance of org.slf4j.Logger incurs no overhead at all. You could directly invoke loggers of type ch.qos.logback.classic.Logger instead of org.slf4j.Logger but doing so does not provide any advantages but will probably make it harder to migrate to a different logging framework if and when you chose to do so.
By the way, slf4j is not a wrapper for logback as logback is implemented in terms of the slf4j-api.
To ease migration to SLF4J, there is a tool for migrating source code to slf4j. For code which can not be modified by you, there are bridges for log4j, java.util.logging and commons-logging.
You may be able to migrate with no code changes at all, using the log4j-over-slf4j.jar instead of the "real" Log4J one. This provides the same API as Log4J to its clients, but directs the logging calls to SLF4J, which in turn can send them to logback.
But if you have the option of modifying the code then I would recommend changing it to use SLF4J, and you can then swap in any back-end as required (logback, log4j, etc). One thing you must not do is try and combine log4j-over-slf4j with the Log4J backend...
There is one very good reason for using the SLF4J api regardless of actual logging backend, namely the
log.debug("Foo: {}, Bar: {}", foo, bar);
parameter construct. Log4j always need a full string to log, which is why you need surrounding ifs to see if the statement is enabled for an expensive string. SLF4J do not call foo.toString() or bar.toString() before doing the check, so disabled calls are cheap.
Hence I would suggest migrating your source to slf4j and use the appropriate bridge in the slf4j download to use log4j as the backend. This will allow you to continue as you do now, without further changes. You can then switch backend to logback if you need to.
I asked a question earlier today about log4j and was told that it is now "legacy" and that I should use slf4j and logback. So now I will use that but I don't understand where to start? slf4j is a abstraction layer over other logging frameworks after what I read but I can't find anything other than really basic hello world logging tutorials? How do I configure slf4j and use it?
Slf4j is the API and yes logback is probably the implementation that you want.
Just use the slf4j logger classes in your code and the add logback.jar and logback.xml to your classpath.
The logback homepage contains a lot of the information you need to get started.
You will be using slf4j with log4j (or any other logging implementation). So if you use log4j with slf4j you will have to provide the configuration for log4j in the log4j.properties. So the advantage is if you want to later change to Logback, you just have to replace the binding jar file(for log4j it may be slf4j-log4j12-1.6.6.jar) with new binding jar and add the configuration for Logback. No change in code.
This thread should help you.SLF4J Manual
We use slf4j + logback, and happened to have some third-party libraries which use commons-logging. How do I set it up to use logback?
The answer is to not use commons-logging.jar, since SLF4J was designed to do what commons-logging does but better. As #MahdeTo refers to, you need to use jcl-over-slf4j.jar.
Check out the documentation from the slf4j website on migrating from commons-logging.
I come across this question too, and found out jcl-over-slf4j.jar indeed can solve the problem, I couldn't understand that why commons-logging couldn't use logback automatically, since commons-logging is log interface and logback is implementation, they should integrate automatically, until I found this:
The Apache Commons Logging (JCL) provides a Log interface that is
intended to be both light-weight and an independent abstraction of
other logging toolkits. It provides the middleware/tooling developer
with a simple logging abstraction, that allows the user (application
developer) to plug in a specific logging implementation.
JCL provides thin-wrapper Log implementations for other logging tools,
including Log4J, Avalon LogKit (the Avalon Framework's logging
infrastructure), JDK 1.4, and an implementation of JDK 1.4 logging
APIs (JSR-47) for pre-1.4 systems. The interface maps closely to Log4J
and LogKit.
Obviously not all the log interface can integrate nicely with log implementation which mean, if you really want to use logback, jcl-over-slf4j.jar is your only solution now because JCL only support Log4J, Logkit, JDK 1.4.
Just add jcl-over-slf4j to the dependencies of your project (check current version at https://search.maven.org/search?q=g:org.slf4j%20AND%20a:jcl-over-slf4j&core=gav)
for those all who wants to keep the final package size smaller; checkout
mvn dependency:tree result of your project and if any dependency to commons-logging exists, exclude them as well. Since the jcl-over-slf4j.jar contains both Log and LogFactory classes with exact same package structure, these commons-logging jars will be extra on your final package.
Are they alternatives, dependencies, APIs or implementations of each other?
And why do they exist?
Ah, logging frameworks in Java. Your question mixes 2 different types of libraries:
log4j and JDK logging are libraries for handling logging
Commons Logging and SLF4J are logging facades: you still need a real logging implementation (like log4j)
If you are writing a library that will be used in someone else's system, then you should use a logging facade because you do not know which logging framework they will use. In this case use SLF4J (Commons Logging is older and has some classloader issues).
If you control the whole application and can dictate which logging framework to use, you are free to choose your own preference. My preferred solutions are (in order of preference):
Logback
log4j
JDK logging (in my opinion, a case of 'not invented here' by SUN)
I've been looking into this recently too. I've been using Log4J for years with Commons Logging and recently switched to SLF4J.
Log4j
Log4j is a framework for actually doing the log writing/distribution. It's extremely flexible: you can direct it to send log messages to files, syslog, remote monitoring, etc. You can also configure multiple loggers, logging categories, include context in entries, and so on. It's one of the most popular logging systems.
JDK Logging
The built-in JDK logging (which I've never used, to be honest) was added in JDK 1.4.2. From what I gather, it's not very popular because it's not as flexible as Log4j, but I'd welcome comments :).
Commons Logging and SLF4j
Both of these are façades on top of various logging frameworks that present a common interface for your application. For example, you can use CL/SLF4J in your application, and they will automatically detect an underlying logger implementation (Log4J, JDK logging, or a built-in logger that just delegates to System.err.println()). The benefit is that you or your end user can decide to switch out the underlying logging implementation at will, and they greatly simplify your implementation by removing many of the complexities of Log4J and JDK logging.
Most often you will see them layered.
SLF4J is purely an abstraction layer and is not, in itself, used for the actual outputting of logging but used by you in your code to log messages.
A typical setup is to use SLF4J to log in your code, then use log4j as the underlying "output" layer using an appropriate slf4j->log4j bridge (a jar you just include on your classpath). In order to merge logging from different sources, various bridges exist. For instance, many app servers (like tomcat) will use JDK-logging to avoid forcing a "non standard" logging framework on the deployed applications. For that purpose, slf4j has a bridge that will pick up all output from JDK-logging. So, this could be a stack
JDK-logging <- Your app-server or framworks might log using this
|
(JDK->Slf4j bridge)
|
Slf4j <- your application logs using Slf4j
|
(Slf4j->log4j bridge)
|
log4j <- log4j is just responsible for outputting to the appenders you configure (file, console etc)
SLF4J just is a generic API with different back-ends (any other logging system). Log4j and commons-logging (CL) different logging libraries, CL is a fossil. But they all have a fatal flaw, so sun have invented JDK logging.
As for me, I prefer SLF4J as most flexible and logback as a backend for it. Logback is most modern and have a lot nice features.