-
Notifications
You must be signed in to change notification settings - Fork 40.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
remove SLF4J dependency from spring-boot-starter-log4j2 #39627
Comments
What issues specifically? SLF4J is a logging abstraction whereas Log4J is a concrete logging implementation/framework. |
@ciscoo there are compatibility concerns with libraries and which SLF4J version is in use, notably logback. both SLF4J and Log4J have logging abstraction APIs, so I think many tend to think of these as alternatives vs one being an impl, even if sometimes one is. If you avoid forcing a specific SLF4J version, then there's no compatibility conflict in that ecosystem. Specifically, in zipkin we have two server builds, and one uses log4J as an impl, the other logback. All of our dependencies that use SLF4J, use version 1.x and none use 2.x. There was an issue where certain logs just didn't appear anymore, and basically we found out it was over incompatibility (after noticing the log4j2 starter actually causes a version side effect on SLF4J). While we were able to get rid of the problem by excluding the dependency, the point that these are both abstractions. It is as weird for log4j2 starter to add a slf4j dep as it is for vise versa to be true, IMHO. you may not agree, but anyway that's why I raised the issue. hopefully to help the next person who discovers this by losing time troubleshooting missing logs. |
It's been quite a while since the logging starters were developed, but I think the logic behind adding SLFJ is that many libraries make use of it for logging and so we wanted to have it as a managed dependency. Whilst it's possible that a user might choose to use only Log4J APIs in their applications, they may need it indirectly when if they start depending on specific libraries. For example, I think Hikari uses SLF4J for logging. I'm not sure what the best option here would be for typical users. If we don't manage the dependency we're likely to have folks hit the same problem but in a more random way (depending on what libraries they use and the transitive dependencies that get pulled in). @codefromthecrypt Have you got more details of the SLF4J 1.x/2.x compatibility issue? Is the problem that libraries compiled against 1.x just don't log correctly when 2.x is used as a replacement? |
yeah this was the battle openzipkin/zipkin#3714 |
The SLF4J dependency is required to route logging that's performed using the SLF4J API into Log4j2. Similarly, we include the Log4j2 API in our Logback-based starter so that logging that's performed using the Log4j2 API can be routed into Logback through SLF4J. If we were to remove one or both, I believe that logging would be lost unless users performed some additional configuration. From an API perspective, my understanding is that SLF4J 2.0 is backwards compatible with SLFJ 1.7. The area where things are incompatible is with the binding of SLF4J to a particular back end and there you need to match things up. This is why the SLF4J and Logback upgrades had to be done together. Having read through openzipkin/zipkin#3714, I don't understand why logging was being lost. It would be very useful to see a minimal example of that so that we can fully understand the cause. Based on my current understanding of SLF4J's backwards compatibility, it should work. If it does not, it may be there there's a bug that can be fixed elsewhere. |
@reta if you recall any specifics on this let us know. @wilkinsona let me try to summarize, as it sounds this is here to stay regardless. Correct me if I'm wrong! Log4J does not require SLF4J, and neither does spring boot. boot has logback marked optional and works without it. However there is gravity around logback in boot and versions should match. To defend against this, there's a dep on slf4j in the log4j2 starter, and that dep matches the version of logback set by the dependencies bom. This is a safeguard to prevent lost logs for folks using logback. Folks that don't require slf4j or want to use an old version can exclude the dep (like we did in zipkin). |
Correct. However, we manage some libraries that do require SLF4J. That is to say, they use the SLF4J API for their logging and if it doesn't get routed somewhere, it gets lost.
That's fair. Logback's our default which has some influence on the choices we make and it is vital that the version of Logback being used is compatible with the version of SLF4J being used. That said, there are also some constraints on the version of SLF4J being used even when Logback isn't being used. More on this below.
Note quite. It's a safeguard to prevent lost logs for anything that uses the SLF4J API. We manage a number of dependencies that do so, including:
Some of these libraries compile against SLF4J 2.0.x and may not work with SLF4J 1.x as there are new APIs in 2.0 that they may be using. From an API perspective, SLF4J 2.0 should be backwards compatible with 1.x so this leads us to using SLF4J 2.0.x as our managed version. I think that makes sense with or without Logback's involvement.
Correct. If you're not using anything that uses the SLF4J API for logging, you can exclude |
Yeah, sure, so there is no binary incompatibilities between LF4J 2.0.x and SLF4J 1.7.x, what changes is the discovery part (initialization). In context of openzipkin/zipkin#3714, we run into a mix where:
The logs were not showing, and as per https://www.slf4j.org/faq.html#changesInVersion200, this is expected. Where Spring Boot made things a bit more complicated is that |
Thanks, @reta. Unfortunately, I'm still confused as to why the problem was occurring. In the SLF4J FAQ I cannot see a situation where nothing will be logged. At worst, you should see a warning that either a binding or a provider could not be found. The FAQ also states that 2.0.x should be a drop-in replacement. In your situation where you have some use of 2.0.x and some use of 1.7.x, resolving that version conflict by using 2.0.x and ensuring that there's a 2.0.x-compatible provider on the classpath such as Logback 1.4 or Log4j2's Can you please share a minimal example that demonstrates that this is not the case? |
Thanks @wilkinsona
Yes, I believe this is the case, and the absence of the binding provider is the cause of no logs being shown up. I should probably clarify here that the logs from Spring Boot itself are there, but not from other components (like
Absolutely, I will try to have one shortly, thank you |
@wilkinsona quick update, I was working on a simple reproducer (and I reproduced the issue) but it seems like the cause is slightly different and is related to the way log4j and slf4j were configured. To explain a bit more in details, using
However replacing it with the
I think this is kind of expected - no provider, no logs. |
Yes, that's to be expected. If you're using SLF4J 2, you need to use |
I think the root takeaway here is "A Spring Boot 3.x app shouldn't use ... SLF4J 1.x". This was the thing that led to me opening this issue, as I mentioned Spring had an opinion on SLF4J 2, someone was surprised I would think that, and here we are. At least we are on the same page! |
Had a chat with @jonatan-ivanov who encouraged me to raise issues on things I feel are bugs. So, I feel that despite being intentionally done in #12649 (and really it started before that), spring-boot-starter-log4j2 having a dependency on SLF4J anything is a bug not a feature.
I can understand the fight over logback and looking for a way out, but it did take some time to understand this, as SLF4J and Log4J are different libraries, and coupling them creates issues that can be tricky to detect. The workaround is to manually exclude the dep, but anyway. over to you!
The text was updated successfully, but these errors were encountered: