chore: add comments explaining the logging system
All checks were successful
ci/woodpecker/push/docs Pipeline was successful
ci/woodpecker/push/jfmod Pipeline was successful

This commit is contained in:
Johannes Frohnmeyer 2024-03-15 11:54:41 +01:00
parent 3c691ffe86
commit c98c713da8
Signed by: Johannes
GPG Key ID: E76429612C2929F4
2 changed files with 14 additions and 0 deletions

View File

@ -30,6 +30,10 @@ public class LibJf implements PreLaunchEntrypoint {
bootstrap(); bootstrap();
if (!setup) { if (!setup) {
setup = true; setup = true;
// Sometimes a mod using LibJF may want to log before game libraries are initialized.
// For that case, an implementation of System.Logger that redirects to Fabric Loader's logger is used at startup.
// After the game is initialized though, that becomes unnecessary, and we can switch to using SLF4J directly.
// The setup method is called after the game is initialized, so this is the perfect place to do this.
HotswapLoggerFinder.updateAllStrategies((name, module, level) -> new SLF4JPlatformLogger(LoggerFactory.getLogger(name))); HotswapLoggerFinder.updateAllStrategies((name, module, level) -> new SLF4JPlatformLogger(LoggerFactory.getLogger(name)));
} }
} }
@ -37,9 +41,16 @@ public class LibJf implements PreLaunchEntrypoint {
public static void bootstrap() { public static void bootstrap() {
if (!bootstrapped) { if (!bootstrapped) {
bootstrapped = true; bootstrapped = true;
// I use System.Logger for logging.
// LibJF ships a service loaded in System.LoggerFinder, which delegates to Fabric Loader and (later on) SLF4J (after setup).
if (LOGGER instanceof DelegateLogger) { if (LOGGER instanceof DelegateLogger) {
// If the ServiceLoader was able to find this service, any Logger generated will be a DelegateLogger since that class is used by the HotswapLoggerFinder.
// This means that redirection to SLF4J is already set up and we don't need to do anything.
LOGGER.debug("HotswapLoggerFinder was loaded successfully. No need to install JULBridge."); LOGGER.debug("HotswapLoggerFinder was loaded successfully. No need to install JULBridge.");
} else { } else {
// If Fabric Loader is run in production, the ServiceLoader may not pick up this implementation quickly enough.
// In that case, the JUL backend is selected and this cannot be changed, so we need to redirect logs from JUL instead.
// The JULBridge does exactly that by redirecting JUL logs to loggers created by its own instance of EarlyLoggerSetup.
JULBridge.install(); JULBridge.install();
LOGGER.debug("JULBridge was installed. If available in your launcher, please enable the ServiceLoader fix for better performance."); LOGGER.debug("JULBridge was installed. If available in your launcher, please enable the ServiceLoader fix for better performance.");
} }

View File

@ -7,6 +7,9 @@ import org.jetbrains.annotations.Nullable;
public class EarlyLoggerSetup extends LeveledLoggerFinder { public class EarlyLoggerSetup extends LeveledLoggerFinder {
static { static {
// When a logger is used before the game is initialized, SLF4J is not yet available.
// To support that, this implementation which redirects to Fabric Loader's internal logging abstraction is used instead.
// After the game is initialized, something calls LibJF.setup (usually preEntry), which replaces this factory with a SLF4J-based one.
HotswapLoggerFinder.updateAllStrategies((name, module, level) -> new LoaderPlatformLogger(name)); HotswapLoggerFinder.updateAllStrategies((name, module, level) -> new LoaderPlatformLogger(name));
} }