2

Slf4j provides libraries to "fool" backend specific codebase into thinking specific backend exists while redirecting all the logging to one slf4j api compatible backend.

In short log4j-over-sl4j will redirect anything from log4j specific logging into slf4j.

So my classpath now has

slf4j-api *-over-slf4j slf4j-simple (to be removed)

I'm trying to provide custom logging backend for slf4j 1.8+ (please don't ask why). In order to get started with this i've copied over slf4j-simple into my project.

When slf4j-simple is added as a dependency logging happens as expected, but when i remove the dependency and simply keep the exact same content in my own codebase it will not pick it up (different package though)...

How can i make sl4j see my custom provider?

enter image description here

UPDATE

I can see that the jar has some extra information possibly what is being used by slf4j to choose the provider...

However in my case my logging backend is in my own codebase (i dont want to separate it into a library), so is there an api to set your provider to SLF4J?

enter image description here

vach
  • 10,571
  • 12
  • 68
  • 106
  • 1
    Does SLF4J find implementations via services? If so, did you create the service provider configuration file (the one that goes in the `META-INF/services` directory)? – Slaw Jun 11 '18 at 06:33
  • @Slaw you're right i can see something in the jar under `META-INF/services`, i didn't about this tool which apparently is there since 1.6. – vach Jun 11 '18 at 06:49
  • For those interested look at https://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html – vach Jun 11 '18 at 06:49

2 Answers2

4

SLF4J 1.8+ (which is in beta as of 12.06.2018) abandoned notion of StaticLoggerBinder and instead is using something better called ServiceLoader.

Once you have a copy of the slf4j-simple source in your own codebase with your own package you only need to create a file at ${projectRoot}/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider and put full classname to your own class that shall be picked up your.package.YourLoggingServiceProvider

Make sure you remove any actual binding to another provider, slf4j will give a clear error message that there are multiple bindings on your classpath.

Now try LoggerFactory.getLogger("something").info("something") it shall pick up your classes for logging...

vach
  • 10,571
  • 12
  • 68
  • 106
  • 1
    Just a note: SLF4J 1.8 is still in BETA. OP should be aware of this in choosing appropriate SLF4J version (hence the corresponding provider mechanism) to be used in your project – Adrian Shum Jun 12 '18 at 03:24
2

Refer to the SLF4J FAQ, "How do I make my logging framework SLF4J compatible?" and surrounding area:

  1. start with a copy of an existing module,
  2. create an adapter between your logging system and org.slf4j.Logger interface
  3. create a factory for the adapter created in the previous step,
  4. modify StaticLoggerBinder class to use the factory you created in the previous step

It doesn't look like your question mentions the StaticLoggerBinder, which is the class that there needs to be exactly one of in order for SLF4J to work. It's how SLF4J finds your specific implementation of the logging interface.

  • it seems is its no longer used, it is using ServiceLoader 1.8+ versions – vach Jun 12 '18 at 01:30
  • You're right for older versions, however for new approach one needs to use https://www.concretepage.com/java/serviceloader-java-example – vach Jun 12 '18 at 01:44
  • Silly me, trusting the documentation to be up-to-date. You'd think I'd have learned that lesson by now. –  Jun 12 '18 at 02:22