It would be extremely useful to bundle the slf4j-simple
logging implementation as a separate artifact (e.g. slf4j-simple-impl
) so that it can be used without exposing it as an automatically detected service provider. (P.S. I didn't realize how cool the name slf4j-simple-impl
is until I just wrote that.) This would involve simply splitting out the implementation code (and perhaps the actual SimpleServiceProvider
class as well, without exposing it as a service) into a separate subproject—little if any actual code changes would be needed.
You can see how I've done something similar with Clogr's https://github.com/globalmentor/clogr/tree/main/clogr-logback and https://github.com/globalmentor/clogr/tree/main/clogr-logback-provider .
This would bring a couple of big wins, notably solving SLF4J-592
: Mechanism for indicating provider to use for unit tests. Let me lay out the use cases:
Basis for Specialized Implementations
Splitting out the slf4j-simple
implementation would allow others to create specialized versions. Without the separate artifact, a specialized version has to duplicate the slf4j-simple
code, because otherwise simply referring to that dependency would expose a provider that would be detected by SLF4J, resulting in "dueling providers".
This is not a theoretical need. Read Solving the Java Aws Lambda logging problem, in which Frank Afriat (@fafriat) investigates how to create a logging implementation that is simple but plays well with AWS Lambda. In theory you would just write to stdout
/stderr
, but there are a couple of gotchas Frank had to work around. He had to fork slf4j-simple
and make a customized version. I believe (although I haven't asked him) that had slf4j-simple-impl
existed, he could have simply used that dependency, added a few tweaks, and then exposed his own provider rather than copying all the code as he has done.
Including/Selecting an Optional Logging Provider
If slf4j-simple-impl
existed, I could include the dependency but not expose SimpleServiceProvider
via the Java service provider mechanism, so that it wouldn't be detected by SLF4J automatically, requiring me to manually "enable it".
In SLF4J-592
: Mechanism for indicating provider to use for unit tests (see also my Maven exclude/remove test dependency defined in parent POM and someone else's Is there any simple pattern of slf4j usage in unit tests?) I pondered how I want logging to work in unit tests. After months of thinking, I finally know:
- By default I want all logging in unit tests to be suppressed during the Maven build and in the IDE.
- However if something goes wrong, I want to send logging to
stderr
during the build, just by setting some flag.
I both cases, I don't want to affect the logging provider used by the artifacts actually being built.
With slf4j-simple-impl
(assuming you put SimpleServiceProvider
inside slf4j-simple-impl
as well, but don't expose it as a Java service provider), I could simply include slf4j-simple-impl
in test
scope in my parent POM. All my tests would automatically get the slf4j-simple-impl
logging implementation, but it wouldn't be used—it would lurking, ready to be enabled.
In my build I would set slf4j.provider
to ….NOP_FallbackServiceProvider
during unit/integration tests. This would address 1) above—all logging in unit tests would be suppressed. This would not conflict with or affect in any way the logging providers of the actual artifacts build for the various libraries and applications.
In my build I would add a Maven debug
profile that I could invoke with -P debug
. This would override slf4j.provider
with ….SimpleServiceProvider
for the unit/integration tests. Suddenly all my unit tests would start logging to stdout
/stderr
(whichever I have configured), helping me to track down problems in the build. This addresses 2) above.
I believe this would be a complete, comprehensive solution to the build unit/integration test logging question. And pulling it off would be so simple. (The only remaining question would be whether to include SimpleServiceProvider
in slf4j-simple-impl
but not expose it as a service; or leave it in slf4j-simple
, requiring consumers to create their own provider wrapper class.)
Note that if you decide not to split out slf4j-simple-impl
, I can easily write my own simple logging implementation—it would just be a shame to reinvent the wheel.
If you think this is a great idea, just let me know and I could probably file a pull request for it.