qos-ch / slf4j

Simple Logging Facade for Java
http://www.slf4j.org
MIT License
2.34k stars 990 forks source link

Added option to load service provider from passed in ClassLoader #337

Open m-froehlich opened 1 year ago

m-froehlich commented 1 year ago

The LoggerFactory will (depending on a System property) load service providers from a passed in ClassLoader, if given. Otherwise previous behavior is maintained. The getLogger(Class) method receives a class, that is used to extract a ClassLoader from.

Signed-off-by: Marvin Fröhlich m.froehlich@infolog.de

m-froehlich commented 1 year ago

Hey ceki, this time I have added a System property to be checked before walking the new path. If the system property is not set, the previous behavior is performed, hence full backwards compatibility. If the property is set to "true", the passed in class'es class loader is prefered when loading ServiceLoaders.

Hope, that is ok this time.

ceki commented 1 year ago

@m-froehlich SLF4J was created in order to avoid the pitfalls of Jakarta Commons Logging in particular its class loader problems.

It follows that SLF4J is designed around a fail fast strategy with respect to provider binding. Either SLF4J finds a provider at initialization time and will work as expected or it will fail immediately.

Your proposal introduces a more flexible strategy but which is also less deterministic. More specifically, how do you know which LoggerFactory.getLogger() method with the correct class parameter is called first?

m-froehlich commented 7 months ago

Sorry for the late response.

Out example is the way, the library is actually used in projects like PAC4J or others. And it is used in a very certain way, which keeps the library from working at all. This fix is necessary for SLF to work. We have to add a code fix any time.

So the question is not, how I know, which getLogger() method is called first. But the actual question is, does the current code work at all with libraries like PAC4J. And it doesn't, if it is used with a non standard class loaded.

Hence it is necessary to have to option to control the behavior like this via a system property. Daniel confirms that btw.

ceki commented 7 months ago

@m-froehlich In slf4j-api version 2.0.9 a "slf4j.provider" system property was introduced. You can specify the provider class explicitly via the "slf4j.provider" system property. This bypasses the service loader mechanism for finding providers and may shorten SLF4J initialization.

For your use case, you can specify your own provider. This provider must be available on the class path. It can then delegate to another provider internally using a class loader of your choice.

m-froehlich commented 7 months ago

That sounds good. We'll try that. Thanks.