Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reactor Core should not initialize SLF4J immediately at startup #3967

Open
sagebind opened this issue Jan 15, 2025 · 1 comment
Open

Reactor Core should not initialize SLF4J immediately at startup #3967

sagebind opened this issue Jan 15, 2025 · 1 comment
Labels
status/need-user-input This needs user input to proceed

Comments

@sagebind
Copy link

Reactor initializes SLF4J logging to be initialized statically before a program's main method runs due to this static block:

static {
resetLoggerFactory();
}

This is less-than-ideal for us, since one of the first things we do in our main is do some housekeeping and SLF4J logger configuration. But because Reactor creates a logger factory statically and then logs a message to it here:

loggerFactory.apply(name).debug("Using Slf4j logging framework");

This forces SLF4J to initialize, and our logging implementation of choice (in our case Logback) to initialize before we've had a chance to configure it how we want to from within main. Reactor should not initialize and then immediately use an SLF4J logger statically.

Motivation

It seems unusual for Reactor to attempt to initialize so much statically. I have not yet run into any other library in the past near-decade since we've been using this method of configuring our logger that attempted to log statically. This is the first and only library that I've attempted to use that was not compatible with our method of configuring loggers.

Desired solution

It seems like other classes such as Hooks in my testing also run statically before main and emit logs, so I am not entirely sure what would have to change. But ideally, logging would be initialized lazily, and no logs should be attempted to be emitted until a Reactor class is actually used at normal runtime.

Considered alternatives

We could rewrite our stack to only use default logger paths and classes such that our logger is able to be initialized in the way we want it to before main gets to run, but this could be quite a bit of work to change for us.

Additional context

@sagebind sagebind added the type/enhancement A general enhancement label Jan 15, 2025
@chemicL
Copy link
Member

chemicL commented Jan 31, 2025

Hey, @sagebind. Thanks for the report.

It seems this has not been brought up until this point so I have a sense that to most users it's not really that surprising as you find it. It actually is quite useful to have it initialize statically and have all the libraries that integrate with reactor-core take advantage of the shared logging setup that doesn't require the user to do much aside from having SLF4J on the classpath.

Since you have no suggestion regarding a solution and neither have I, let's think perhaps how you could work around this to still be able to achieve what you intend. I tried experimenting a bit to understand your concern. I came up with the following demo. Please note the comments.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Hooks;

public class Main {

	private static final Logger logger = LoggerFactory.getLogger(Main.class);

	public static void main(String[] args) {
		logger.info("Hello, world!"); // <1>
		Hooks.enableAutomaticContextPropagation(); // <2>
		Flux.just("Hello").subscribe(logger::info); // <3>
		// <1> initializes slf4j
		// <2> first use of Hooks means the static initializer is involved
		//     and in turn initializes the reactor.util.Logger instance
		//     by delegating to the static initializer of reactor.util.Loggers
		// <3> direct use of slf4j
	}
}

As far as I can tell, SLF4J does not get affected by Reactor when <1> is executed. The static initializers don't get exercised until you actually use a particular class. Until you actually call into any library that uses Reactor you should be able to perform any customization that you require.

I look forward to your feedback since I might not really know your codebase and without a reproducible example it is difficult to see where the problem lies.

@chemicL chemicL added status/need-user-input This needs user input to proceed and removed type/enhancement A general enhancement labels Jan 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status/need-user-input This needs user input to proceed
Projects
None yet
Development

No branches or pull requests

2 participants