asarkar / jsemver

Kotlin/Java implementation of the Semantic Versioning specification

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Logback should not be a runtime transitive dependency

Javaru opened this issue · comments

As noted in the SLF4J documentation, libraries should not impose a logging framework on their end-users:

Basic rule: Embedded components such as libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on slf4j-api.

This is so that the end-user can either choose the desired logging framework for their application, or they themselves can conform to this rule when writing a library. In my case, since I am writing an IntelliJ IDEA plugin, I cannot include a backing logging framework in my dependency graph. While I personally prefer logback, I must use the logging framework built-in to the application. When I use jsemver out of the box, I'm getting an SLF4J multiple bindings error. While this is solved by adding an exclude to a build, it does place an unnecessary burden on the user of the jsemver library.

The easiest solution would be to make logback a testRuntimeOnly dependency and move the logback.xml file to src\test\resources.

Removing the logback dependency from main classpath would mean the application logs won't be visible unless the user explicitly adds a logging implementation. This would also need to be documented. I'm not convinced that asking the user to configure the logging is better than them adding an exclusion in the build file. I'm also not convinced that the number of users who want logging to work OOTB are fewer in number than those who want to configure logging explicitly. It's six of one, half a dozen of the other.

That said, I'm open to moving the src/main/resources/logback.xml to src/test/resources/logback-test.xml so that the user is free choose their own logging configuration. If that helps, you're welcome to submit a PR.

Thanks for the reply. Here are my thoughts. Please forgive the length, but I feel its important to address your various points. And I think this is an important issue.

Removing the logback dependency from main classpath would mean the application logs won't be visible unless the user explicitly adds a logging implementation.

Understood. But in the long run, this is by far the lesser of the two evils. It is not uncommon to have to turn on additional logging/output. Whether via adding a logging framework, turning on the DEBUG level in a logging configuration, or in the case of CLI apps, using a ---verbose or --debug switch. And libraries/applications should always favor their end state use, not their initial exploratory use.

This would also need to be documented.

I think either way, it needs to be documented. i.e. either to include a backing framework of your choice, or to exclude the logback dependency if undesired. In the case of documenting adding a backing framework, you can simply point to the SLF4J documentation for Binding with a logging framework at deployment time. And then perhaps add a sentence or two to say "For example, to use the recommended Logback framework, add this dependency to your build: show gradle and maven dependency declaration example

I'm also not convinced that the number of users who want logging to work OOTB are fewer in number than those who want to configure logging explicitly. It's six of one, half a dozen of the other.

I have to respectfully disagree here. First, while it might be expectant for an application that logging work OOTB, I do not think this holds true for a library. In fact, I personally, and I strongly believe most developers, expect to have to turn on logging for any library being used. Not to turn it off when used in an application. Secondly, I think is it much more a 90:10 thing (if not 99:1) rather than a 50:50 thing (as implied by the "six of one, half a dozen of the other" comment.) jsemver is clearly a library and not a standalone application. As such, for almost all uses, it will be used in another application , library, or framework. And ultimately it is up the end application, or even in many cases the deployment environment of an application (i.e. the ultimate end user), to decided what logging framework to use. That is the power of SL4FJ. In fact the entire reason SLF4J was written was so that a logging framework could be bound at runtime by the end user rather than at compile time by the developer. (See The Logging Mess) This is why it is clearly noted as a basic rule in the SLF4J documentation, as quoted in my original post, to not include a logging framework in a library. (And if you are not familiar, Ceki Gulcu, the founder of Log4J and writer of SLF4J and Logback, is the zen master of logging 😂, especially in the Java world. So I explicitly trust his recommendations. )

If all libraries followed the philosophy of automatically including a logging framework and that users can "just exclude them", this means a user may have to add dozens and dozens of exclude statements, if not scores and scores of them, to their build to not include various binding frameworks. As opposed to a single dependency to declare a desired logging framework. When all reciprocal transitives are taken into consideration, an applications can pull in hundreds, and sometimes thousands, of dependencies. The task of finding all the dependencies is pulling in a logging framework, either directly or via a deeply nested transitive dependency, and then adding the needed exclusions it is very time consuming. In the past in my work, on multiple occasions I have spent a full day or two working through a large enterprise application's dependency graph excluding logging frameworks from being pulled in. Thankfully this has improved in recent years as SLF4J (and then Log4J 2.0 with its separate API and backing framework JARs) has become more mainstream, and there is better awareness of this issue in the industry.

And it's that last point that I think is important. Standard industry practice today is to not include a backing logging framework. I challenge you to show me a mainstream library that pulls in a logging framework. Versus the hundreds that do not.

I tend to be very passionate about logging. 🙂 Having worked in Java since its first release 25 years ago, I have lived through all the ups and downs of logging in Java. From having nothing, to the well intended but ultimately problematic commons-logging, to the rise of log4j a success story, but one that taught us a lot, to the missed opportunity of the java.util.logging implementation in Java 1.4, to the final rise of SLF4J, along with its misunderstood binding requirements. To today, where we have near logging nirvana. During this all, I spearheaded the logging standards at my company (a large organization with a little over 10,000 developers worldwide) to finally bring an end to all the problems that were occurring when different internal libraries where pulling in different logging frameworks.

I can honestly say that including a logging framework in jsemver will limit its adoption by some users. In our enterprise we favor frameworks/libraries that do not pull in backing logging frameworks, even when providing better functionality, because of all the problems and nightmares we have when logging frameworks are pulled in. I know of other enterprises and projects with similar policies. This means if I were looking for a semantic version library at work rather than for a personal open source project, I'd have to pass on jsemver and use something else. That'd be a shame since after evaluating four different ones, I think jsemver is superior to the others.

Thanks. And thanks for this fine library.

As the author of the library, I reserve the right to make design decisions, and my decision is that logback is staying as a runtime dependency. I'm not participating in a popularity contest, so if someone passes on this library because they are too lazy to add a build exclusion, I won't miss them. As previously mentioned, you're welcome to submit a PR to move the logback.xml file.

Sorry. I interpreted your first response as you being undecided and looking to have some additional technical discussion on the matter. If I misinterpreted that, I apologise.