[slf4j-user] Fail Silently on NOP implementation

Phillip Lord phillip.lord at russet.org.uk
Thu Apr 28 15:13:03 UTC 2016


Marshall Pierce <marshall at mpierce.org> writes:

> The job of slf4j-api is just to be the developer-side interface to logging. It
> purposely delegates the decision of what to do with those logs to the end
> user. I think it is a mistake to include policy mechanisms like these into the
> API.
>
> If you’re writing a library, don’t include a binding. If you’re writing a
> tool, select a binding.

I do not understand this distinction. I have some software which can provides
an interactive shell that I can use directly (i.e. a tool) or which can
be used as a dependency by downstream applications (i.e. a library).
Conclusion I should select a binding, and not include one.

> It is an error to not include a binding, and that’s why it prints to
> stderr. If you’re writing a tool and you want silence, use nop. If
> you’re not writing a tool, it’s not your decision.

I am writing both.


> Regarding slf4j-silent / slf4j-strict: This is just another “policy via
> classpath” mechanism. If you want to control the output of calls made via
> slf4j-api, we already have a mechanism for this. What happens when both are on
> the classpath? As a new user to SLF4J, would you really enjoy learning how to
> use dependency excludes as a debugging tool during your “why won’t my logging
> show up” journey rather than having a clear error message that informs you
> that you’re doing it wrong, and pointing you towards the URL with more info?

Indeed. But, as a non-user of SLF4J would you really enjoy learning
about how to turn off an error message for a library that you are not
using, but which any of your transitive dependencies has chosen to use?

In fact, given the approach above, all you would need is to change your
advice: use slf4j-api when developing, but deploy your artifacts with
slf4j-silent. The hello world default case would behave as now. In
practice, I think, most library developers will need to use a different
dev dependency environment anyway (with logging on) and during
deployment (with logging off).

> This complicates logging, and the debugging thereof, without a clear gain.

The clear gain is that the SLF4J is not going to printing error messages
to people who have not deliberately chosen to use it. I can understand,
of course, why it might prefer the needs of its users over those who are
not. But, it doesn't take too much googling to find quite a few people
asking "where is this error message coming from, and what is SLF4J".

> The fundamental issue is that you’re trying to use the same artifact as both a
> library and an end-user tool (which I’ll define as “a thing with a main method
> or equivalent”). This is an antipattern because there are conflicting goals
> for libraries and tools, as you’ve correctly identified. 

I'm writing in Clojure -- so all things have a main method. Also true of
scala, groovy, javascript and, indeed, Java from 1.9 onwards with
jshell. So, not an antipattern at all, just business as usual.

The JVM is a big ecosystem; bigger than Java.


> If your users will consume your code in two different ways, then it is
> sensible to have two different artifacts.


Well, by this argument, SLF4J is being consumed in two different ways.
In which case, it should have two different artifacts. This seems, to
me, a more sensible approach than suggesting that all downstream
dependencies of SLF4J should have a "thing-with-slf4j-api" and
"thing-with-slf4j-nop" artifacts.

Anyway, it would be good to know if there is any chance of finding a
solution to this at the SLF4J level. Otherwise, I'll just put a nop
binding into my artifact and leave it at that.

Phil


More information about the slf4j-user mailing list