-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
I didn't realize SLF4J-450 was already implemented, so I was excited to look into this. Thanks for the work on this, @ceki and @KengoTODA.
In the source code I see:
static SLF4JServiceProvider loadExplicitlySpecified(ClassLoader classLoader) {
String explicitlySpecified = System.getProperty(PROVIDER_PROPERTY_KEY);
if (null == explicitlySpecified || explicitlySpecified.isEmpty()) {
return null;
}
try {
String message = String.format("Attempting to load provider \"%s\" specified via \"%s\" system property", explicitlySpecified, PROVIDER_PROPERTY_KEY);
Util.report(message);
…
Unfortunately this logs a message to stderr
every time we use the slf4j.provider
property. I don't quite understand the point of that. Logging something to stderr
outside of the normal SLF4J logging system should only be done as a last resort, if there is some unexpected error. For example, if no logger implementation is present, SLF4J indicates, "No SLF4J providers were found."
. The point here is that the user should be warned if they inadvertently don't include a logging implementation. (I'm not sure I fully agree with that decision, but I certain understand the motivation.)
But there is nothing inadvertent about the slf4j.provider
. If you include it, you know you're specifically requesting a logging provider. You don't need SLF4J to remind you of that. If SLF4J uses a provider it finds on the classpath, SLF4J doesn't send a message to stderr
notifying the user of which provider they chose. I don't see the difference here—if any thing, there is less of a reason to log information, because nothing happened "by default"—there was an explicit configuration.
Let's say that I want all my unit tests to ignore all logging output of the libraries they use, so that I won't have to have a logging implementation in test
scope at all. (See SLF4J-592.) By default SLF4J does a a NOP, so I could just leave it at that, except that all my unit tests will have this:
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
SLF4J-450 should fix that! Now I can do this in JUnit:
@BeforeAll
static void disableLogging() {
System.setProperty("slf4j.provider", NOP_FallbackServiceProvider.class.getName());
}
Now I get the following, which defeats the purpose of what I was trying to do. 🤦♂️
SLF4J: Attempting to load provider "org.slf4j.helpers.NOP_FallbackServiceProvider" specified via "slf4j.provider" system property
I can do an ugly hack to get rid of the message:
@BeforeAll
static void disableLogging() {
System.setProperty("slf4j.provider", NOP_FallbackServiceProvider.class.getName());
final PrintStream originalSystemErr = System.err;
try {
System.setErr(new PrintStream(OutputStream.nullOutputStream()));
LoggerFactory.getILoggerFactory();
} finally {
System.setErr(originalSystemErr);
}
}
That suppresses the message. But if I'm going to do that, there's no point in using slf4j.provider
at all, because SLF4J would default to the NOP provider anyway.
Please remove messages to stderr
when slf4j.provider
is used. Or just let me know that you're OK with this change, and I can file a pull request.