[slf4j-user] Recommendation for library writers: use thiscopy and paste wrapper around SLF4j to avoid default static initialization
Adam Gent
adam.gent at snaphop.com
Sat Mar 18 00:35:36 CET 2017
Ceki,
Excellent points! I get little too idealistic on Fridays :).
The heart of issue is intercepting SL4J initialization and critical
control of a specific libraries logging.
This maybe solved in later versions of SLF4J through something like
the ServiceLoader (perhaps even an optional static method on
LoggerFactory.getLogger("LibraryName", Clazz<?>)) and then filter the
ServiceLoader LoggerFactory based on "LibraryName". But I worry that
may complicate SLF4J when most libraries and applications do not care
about initialization.
On the other hand for some reason many libraries really do need a
crosscutting filtering name as they do not use (or abuse) logger name
hierarchy correctly (usually the logger is something like HTTPOUT or
something ridiculous like that). Marker would be ideal for this but
for some reason Marker never really took off. So I could improve the
copy'n paste with a LoggingFactory that decorates all Loggers by
automatically passing a Marker representing the libraries name. Again
this would be just a recommendation for sophisticated libraries... not
all libraries.
The current wrapper I'm proposing for most libraries could (and
probably should) just do the default LoggerFactory.getLogger() and
probably not the NOPLoggerFactory().
Thus configuration would not change for most libraries (since they
would be doing the default LoggerFactory.getLogger()) and would allow
application developers to bootstrap initialization of logging for
libraries that are used for the bootstrap process.
Also while logback and other libraries do allow powerful filtering not
all libraries are new enough (e.g. log4j) and even then in some cases
the performance is still slower than a hard wired NOPLogger.
> You need to consider the Kantian argument. What will happen if every library developer follows your pattern? In my opinion, the situation will be not just bad but completely untenable for the end-user.
In hindsight I was embarrassingly overzealous about saying all
libraries should do this but for sure there are several that
absolutely need to intercept SLF4J initialization or maybe logging is
only used for development of the library. Otherwise the writers of
these libraries go off and make their own crappy wrappers anyway and
use system properties to enable logging. Those wrappers are often far
worse than the SLF4J implementation code in slf4j-api and I think the
wrapper I'm proposing is a fair compromise to actually encourage
greater adoption of SLF4J particularly its API.
On Fri, Mar 17, 2017 at 6:47 PM, Ceki Gülcü <ceki at qos.ch> wrote:
>
> Hi Adam,
>
> --------------
> Quoting from https://www.slf4j.org/faq.html#optional_dependency
>
> It is reasonable to assume that in most projects Wombat will be one
> dependency among many. If each library had its own logging wrapper, then
> each wrapper would presumably need to be configured separately. Thus,
> instead of having to deal with one logging framework, namely SLF4J, the user
> of Wombat would have to detail with Wombat's logging wrapper as well. The
> problem will be compounded by each framework that comes up with its own
> wrapper in order to make SLF4J optional. (Configuring or dealing with the
> intricacies of five different logging wrappers is not exactly exciting nor
> endearing.)
> --------------
>
>
> --------------
> Quoting from: http://stackoverflow.com/a/11360517/100970
> and http://stackoverflow.com/a/11359358/100970
>
> Except the end user could have already done this customization for his own
> code, or another library that uses log4j or LogBack. jul is extensible, but
> having to extend LogBack, jul, log4j and God only knows which other logging
> framework because he uses 4 libraries that use 4 different logging
> frameworks is cumbersome. By using slf4j, you allow him to configure the
> logging frameworks he wants. not the one you have chosen. Remember that
> typical projects use myriads of libraries, and not just yours.
> --------------
>
> You need to consider the Kantian argument. What will happen if every library
> developer follows your pattern? In my opinion, the situation will be not
> just bad but completely untenable for the end-user.
>
> --
> Ceki
>
> On 3/17/2017 22:28, Adam Gent wrote:
>>
>> Yes as noted in my not really javadoc comment:
>>
>> /*
>> * Simply prefix Internal in front of LoggerFactory:
>> * So instead of:
>> * Logger logger = LoggerFactory.getLogger(MyClass.class);
>> * It should be:
>> * Logger logger = InternalLoggerFactory.getLogger(MyClass.class);
>> */
>>
>> Obviously this creates tight coupling with LoggerService but that is
>> OK because LoggerService is expected to be a copy and paste snippet
>> (that is each library should have its own namespace LoggerService). It
>> could also be multiple files. I just made it one file to encourage
>> easy copy and paste.
>>
>> I use LoggerService in my own message bus library (it is a library
>> that is sort of like hystrix + guava eventbus + amqp + reactivestreams
>> that I plan on open sourcing someday). This library does it for
>> performance reasons.
>>
>> I also have a configuration facade framework as well that has an
>> opensource start here https://github.com/agentgt/configfacade . Our
>> internal version is far more sophisticated as well as actually
>> production quality and is the one that uses its own LoggerService as
>> well. This library does it for bootstrap reasons and to beat the
>> logging frameworks initialization.
>>
>>
>> I have seen other libraries that refuse to use SLF4J directly though
>> because of its static binding. Many JBoss libraries IIRC such as
>> RestEasy:
>> https://bill.burkecentral.com/2012/05/22/write-your-own-logging-abstraction/
>>
>> Of course these libraries could have just wrapped the LogFactory
>> creation but instead implement their own logging wrapper which is a
>> lot more code as well as not implementing logging parameter
>> replacement at all or correctly ("{}").
>>
>> -Adam
>>
>> On Fri, Mar 17, 2017 at 4:36 PM, Ceki Gülcü <ceki at qos.ch> wrote:
>>>
>>>
>>> Hi Adam,
>>>
>>> Using ServiceLoader.load(LoggerService.class) is quite a good idea. I
>>> think
>>> we will have to go that way in future versions of SLF4J to be compatible
>>> with Java 9.
>>>
>>> I suppose your library code no longer invokes
>>> org.slf4j.LoggerFactory.getLogger(). How do you use LoggerService in
>>> your
>>> libraries?
>>>
>>> On 3/17/2017 16:51, Adam Gent wrote:
>>>>
>>>>
>>>> Many library writers want to use SLF4j but may want to avoid the
>>>> default initialization and binding process. In fact if it is a library
>>>> and not a framework I recommend something like what I'm proposing.
>>>>
>>>> I have written a single very small copy and paste class that you can
>>>> put in your own library to avoid default SLF4J initialization while
>>>> allowing consumers of your library to pick whatever SLF4J
>>>> initialization they like through the ServiceLoader mechanism. The
>>>> class is meant to be copied and pasted such that you pick your own
>>>> package (namespace) for the ServiceLoader part.
>>>>
>>>> The code is available at this github gist:
>>>>
>>>> https://gist.github.com/agentgt/28dc6e9724cb8b96ca08fc147476a7de
>>>>
>>>>
>>>> There are several reasons why if you are a library writer to consider
>>>> this pattern:
>>>>
>>>> * Often library users don't want to see the annoying default missing
>>>> slf4 binding messages
>>>> * Performance reasons. By defaulting to NOP you prevent accidental
>>>> performance problems by a user of the library.
>>>> * You allow for even greater logging configuration and separation
>>>> than possible with SL4J. For example one library could be configured
>>>> to use a Logback SLF4J and another Log4j legacy SLF4J.
>>>> * If the library used to configured a down stream logging framework
>>>> (ie logback) you might need interception (ie SubstituteLogger).
>>>>
>>>> Thoughts?
>>>>
>>>> I'm hoping perhaps the SL4J documentation recommend something like
>>>> this for library writers.
>>>>
>>>> -Adam
>>>>
>>> _______________________________________________
>>> slf4j-user mailing list
>>> slf4j-user at qos.ch
>>> http://mailman.qos.ch/mailman/listinfo/slf4j-user
>>
>>
>>
>>
> _______________________________________________
> slf4j-user mailing list
> slf4j-user at qos.ch
> http://mailman.qos.ch/mailman/listinfo/slf4j-user
--
CTO
SnapHop (snaphop.com)
(twitter) @agentgt (linkedin) http://www.linkedin.com/in/agentgt
(cell) 781-883-5182
More information about the slf4j-user
mailing list