diff --git a/integration/src/test/java/org/slf4j/OutputVerifier.java b/integration/src/test/java/org/slf4j/OutputVerifier.java index 79ae0e8da..fbc71a159 100755 --- a/integration/src/test/java/org/slf4j/OutputVerifier.java +++ b/integration/src/test/java/org/slf4j/OutputVerifier.java @@ -28,12 +28,12 @@ static void noProvider(StringPrintStream sps) { } { String s = (String) sps.stringList.get(2); - assertTrue(s.contains("SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.")); + assertTrue(s.contains("See https://www.slf4j.org/codes.html#noProviders for further details.")); } { String s = (String) sps.stringList.get(3); - assertTrue(s.contains("SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier.")); + assertTrue(s.contains("Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier.")); } { diff --git a/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java b/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java index 81cef277b..a9f9851ca 100755 --- a/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java +++ b/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java @@ -43,6 +43,7 @@ import org.slf4j.event.SubstituteLoggingEvent; import org.slf4j.helpers.NOP_FallbackServiceProvider; +import org.slf4j.helpers.Reporter; import org.slf4j.helpers.SubstituteLogger; import org.slf4j.helpers.SubstituteServiceProvider; import org.slf4j.helpers.Util; @@ -148,7 +149,7 @@ private static void safelyInstantiate(List providerList, I SLF4JServiceProvider provider = iterator.next(); providerList.add(provider); } catch (ServiceConfigurationError e) { - Util.report("A SLF4J service provider failed to instantiate:\n" + e.getMessage()); + Reporter.error("A service provider failed to instantiate:\n" + e.getMessage()); } } @@ -197,9 +198,9 @@ private final static void bind() { reportActualBinding(providersList); } else { INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION; - Util.report("No SLF4J providers were found."); - Util.report("Defaulting to no-operation (NOP) logger implementation"); - Util.report("See " + NO_PROVIDERS_URL + " for further details."); + Reporter.warn("No SLF4J providers were found."); + Reporter.warn("Defaulting to no-operation (NOP) logger implementation"); + Reporter.warn("See " + NO_PROVIDERS_URL + " for further details."); Set staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet(); reportIgnoredStaticLoggerBinders(staticLoggerBinderPathSet); @@ -218,18 +219,18 @@ static SLF4JServiceProvider loadExplicitlySpecified(ClassLoader classLoader) { } try { String message = String.format("Attempting to load provider \"%s\" specified via \"%s\" system property", explicitlySpecified, PROVIDER_PROPERTY_KEY); - Util.report(message); + Reporter.info(message); Class clazz = classLoader.loadClass(explicitlySpecified); Constructor constructor = clazz.getConstructor(); Object provider = constructor.newInstance(); return (SLF4JServiceProvider) provider; } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { String message = String.format("Failed to instantiate the specified SLF4JServiceProvider (%s)", explicitlySpecified); - Util.report(message, e); + Reporter.error(message, e); return null; } catch (ClassCastException e) { String message = String.format("Specified SLF4JServiceProvider (%s) does not implement SLF4JServiceProvider interface", explicitlySpecified); - Util.report(message, e); + Reporter.error(message, e); return null; } } @@ -238,12 +239,12 @@ private static void reportIgnoredStaticLoggerBinders(Set staticLoggerBinder if (staticLoggerBinderPathSet.isEmpty()) { return; } - Util.report("Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier."); + Reporter.warn("Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier."); for (URL path : staticLoggerBinderPathSet) { - Util.report("Ignoring binding found at [" + path + "]"); + Reporter.warn("Ignoring binding found at [" + path + "]"); } - Util.report("See " + IGNORED_BINDINGS_URL + " for an explanation."); + Reporter.warn("See " + IGNORED_BINDINGS_URL + " for an explanation."); } @@ -269,7 +270,7 @@ static Set findPossibleStaticLoggerBinderPathSet() { staticLoggerBinderPathSet.add(path); } } catch (IOException ioe) { - Util.report("Error getting resources from path", ioe); + Reporter.error("Error getting resources from path", ioe); } return staticLoggerBinderPathSet; } @@ -294,7 +295,7 @@ private static void fixSubstituteLoggers() { static void failedBinding(Throwable t) { INITIALIZATION_STATE = FAILED_INITIALIZATION; - Util.report("Failed to instantiate SLF4J LoggerFactory", t); + Reporter.error("Failed to instantiate SLF4J LoggerFactory", t); } private static void replayEvents() { @@ -343,22 +344,22 @@ private static void replaySingleEvent(SubstituteLoggingEvent event) { substLogger.log(event); } } else { - Util.report(loggerName); + Reporter.warn(loggerName); } } private static void emitSubstitutionWarning() { - Util.report("The following set of substitute loggers may have been accessed"); - Util.report("during the initialization phase. Logging calls during this"); - Util.report("phase were not honored. However, subsequent logging calls to these"); - Util.report("loggers will work as normally expected."); - Util.report("See also " + SUBSTITUTE_LOGGER_URL); + Reporter.warn("The following set of substitute loggers may have been accessed"); + Reporter.warn("during the initialization phase. Logging calls during this"); + Reporter.warn("phase were not honored. However, subsequent logging calls to these"); + Reporter.warn("loggers will work as normally expected."); + Reporter.warn("See also " + SUBSTITUTE_LOGGER_URL); } private static void emitReplayWarning(int eventCount) { - Util.report("A number (" + eventCount + ") of logging calls during the initialization phase have been intercepted and are"); - Util.report("now being replayed. These are subject to the filtering rules of the underlying logging system."); - Util.report("See also " + REPLAY_URL); + Reporter.warn("A number (" + eventCount + ") of logging calls during the initialization phase have been intercepted and are"); + Reporter.warn("now being replayed. These are subject to the filtering rules of the underlying logging system."); + Reporter.warn("See also " + REPLAY_URL); } private final static void versionSanityCheck() { @@ -372,9 +373,9 @@ private final static void versionSanityCheck() { } } if (!match) { - Util.report("The requested version " + requested + " by your slf4j provider is not compatible with " + Reporter.warn("The requested version " + requested + " by your slf4j provider is not compatible with " + Arrays.asList(API_COMPATIBILITY_LIST).toString()); - Util.report("See " + VERSION_MISMATCH + " for further details."); + Reporter.warn("See " + VERSION_MISMATCH + " for further details."); } } catch (java.lang.NoSuchFieldError nsfe) { // given our large user base and SLF4J's commitment to backward @@ -383,7 +384,7 @@ private final static void versionSanityCheck() { // emit compatibility warnings. } catch (Throwable e) { // we should never reach here - Util.report("Unexpected problem occurred during version sanity check", e); + Reporter.error("Unexpected problem occurred during version sanity check", e); } } @@ -398,18 +399,18 @@ private static boolean isAmbiguousProviderList(List provid */ private static void reportMultipleBindingAmbiguity(List providerList) { if (isAmbiguousProviderList(providerList)) { - Util.report("Class path contains multiple SLF4J providers."); + Reporter.warn("Class path contains multiple SLF4J providers."); for (SLF4JServiceProvider provider : providerList) { - Util.report("Found provider [" + provider + "]"); + Reporter.warn("Found provider [" + provider + "]"); } - Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation."); + Reporter.warn("See " + MULTIPLE_BINDINGS_URL + " for an explanation."); } } private static void reportActualBinding(List providerList) { // binderPathSet can be null under Android if (!providerList.isEmpty() && isAmbiguousProviderList(providerList)) { - Util.report("Actual provider is of type [" + providerList.get(0) + "]"); + Reporter.info("Actual provider is of type [" + providerList.get(0) + "]"); } } @@ -452,9 +453,9 @@ public static Logger getLogger(Class clazz) { if (DETECT_LOGGER_NAME_MISMATCH) { Class autoComputedCallingClass = Util.getCallingClass(); if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) { - Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(), + Reporter.warn(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(), autoComputedCallingClass.getName())); - Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation"); + Reporter.warn("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation"); } } return logger; diff --git a/slf4j-api/src/main/java/org/slf4j/MDC.java b/slf4j-api/src/main/java/org/slf4j/MDC.java index ec6cb76c4..6ba316453 100644 --- a/slf4j-api/src/main/java/org/slf4j/MDC.java +++ b/slf4j-api/src/main/java/org/slf4j/MDC.java @@ -30,6 +30,7 @@ import org.slf4j.helpers.BasicMDCAdapter; import org.slf4j.helpers.NOPMDCAdapter; +import org.slf4j.helpers.Reporter; import org.slf4j.helpers.Util; import org.slf4j.spi.MDCAdapter; import org.slf4j.spi.SLF4JServiceProvider; @@ -92,8 +93,8 @@ private MDC() { if (provider != null) { mdcAdapter = provider.getMDCAdapter(); } else { - Util.report("Failed to find provider."); - Util.report("Defaulting to no-operation MDCAdapter implementation."); + Reporter.error("Failed to find provider."); + Reporter.error("Defaulting to no-operation MDCAdapter implementation."); mdcAdapter = new NOPMDCAdapter(); } } diff --git a/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java b/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java index 441702b1c..0b15d6ff1 100644 --- a/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java +++ b/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java @@ -25,6 +25,7 @@ package org.slf4j; import org.slf4j.helpers.BasicMarkerFactory; +import org.slf4j.helpers.Reporter; import org.slf4j.helpers.Util; import org.slf4j.spi.SLF4JServiceProvider; @@ -53,8 +54,8 @@ private MarkerFactory() { if (provider != null) { MARKER_FACTORY = provider.getMarkerFactory(); } else { - Util.report("Failed to find provider"); - Util.report("Defaulting to BasicMarkerFactory."); + Reporter.error("Failed to find provider"); + Reporter.error("Defaulting to BasicMarkerFactory."); MARKER_FACTORY = new BasicMarkerFactory(); } } diff --git a/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java b/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java index 707b4c6f3..47f95daaa 100755 --- a/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java +++ b/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java @@ -291,7 +291,7 @@ private static void safeObjectAppend(StringBuilder sbuf, Object o) { String oAsString = o.toString(); sbuf.append(oAsString); } catch (Throwable t) { - Util.report("SLF4J: Failed toString() invocation on an object of type [" + o.getClass().getName() + "]", t); + Reporter.error("Failed toString() invocation on an object of type [" + o.getClass().getName() + "]", t); sbuf.append("[FAILED toString()]"); } diff --git a/slf4j-api/src/main/java/org/slf4j/helpers/Reporter.java b/slf4j-api/src/main/java/org/slf4j/helpers/Reporter.java new file mode 100644 index 000000000..790010f44 --- /dev/null +++ b/slf4j-api/src/main/java/org/slf4j/helpers/Reporter.java @@ -0,0 +1,121 @@ +package org.slf4j.helpers; + +import java.io.PrintStream; + +/** + * An internally used class for reporting messages generated by SLF4J itself during initialization + * + * @since 2.0.10 + */ +public class Reporter { + + /** + * this class is used internally by Reporter + */ + private enum Level { + INFO(1), WARN(2), ERROR(3); + + int levelInt; + + private Level(int levelInt) { + this.levelInt = levelInt; + } + + private int getLevelInt() { + return levelInt; + } + } + + private enum TargetChoice { + Stderr, Stdout; + } + + static final String SLF4J_INFO_PREFIX = "SLF4J(I): "; + static final String SLF4J_WARN_PREFIX = "SLF4J(W): "; + static final String SLF4J_ERROR_PREFIX = "SLF4J(E): "; + + + /** + * Acceptable values are s "System.out", "stdout", "sysout", "System.err", "stderr" and "syserr". + */ + public static final String SLF4J_REPORT_TARGET_KEY = "slf4j.reportStream"; + + + public static final String SLF4J_VERBOSITY_KEY = "slf4j.verbosity"; + static private final String[] SYSOUT_KEYS = {"System.out", "stdout", "sysout"}; + + static private final TargetChoice TARGET_CHOICE = initTargetChoice(); + + static private final Level VERBOSITY = initVerbosity(); + + static private TargetChoice initTargetChoice() { + String reportStreamStr = System.getProperty(SLF4J_REPORT_TARGET_KEY); + + if(reportStreamStr == null || reportStreamStr.isEmpty()) { + return TargetChoice.Stderr; + } + + for(String s : SYSOUT_KEYS) { + if(s.equalsIgnoreCase(reportStreamStr)) + return TargetChoice.Stdout; + } + return TargetChoice.Stderr; + } + + + static private Level initVerbosity() { + String verbosityStr = System.getProperty(SLF4J_VERBOSITY_KEY); + + if(verbosityStr == null || verbosityStr.isEmpty()) { + return Level.INFO; + } + + if(verbosityStr.equalsIgnoreCase("ERROR")) { + return Level.ERROR; + } + + + if(verbosityStr.equalsIgnoreCase("WARN")) { + return Level.WARN; + } + + return Level.INFO; + } + + static boolean isEnabledFor(Level level) { + return (level.levelInt >= VERBOSITY.levelInt); + } + + static private PrintStream getTarget() { + switch(TARGET_CHOICE) { + case Stdout: return System.out; + case Stderr: + default: return System.err; + } + } + + public static void info(String msg) { + if(isEnabledFor(Level.INFO)) { + getTarget().println(SLF4J_INFO_PREFIX + msg); + } + } + + static final public void warn(String msg) { + if(isEnabledFor(Level.WARN)) { + getTarget().println(SLF4J_WARN_PREFIX + msg); + } + } + + static final public void error(String msg, Throwable t) { + // error cannot be disabled + getTarget().println(SLF4J_ERROR_PREFIX + msg); + getTarget().println(SLF4J_ERROR_PREFIX + "Reported exception:"); + t.printStackTrace( getTarget()); + } + + + static final public void error(String msg) { + // error cannot be disabled + getTarget().println(SLF4J_ERROR_PREFIX + msg); + } +} diff --git a/slf4j-api/src/main/java/org/slf4j/helpers/Util.java b/slf4j-api/src/main/java/org/slf4j/helpers/Util.java index 19b8af559..39a74a8a9 100755 --- a/slf4j-api/src/main/java/org/slf4j/helpers/Util.java +++ b/slf4j-api/src/main/java/org/slf4j/helpers/Util.java @@ -117,14 +117,14 @@ public static Class getCallingClass() { return trace[i + 2]; } - static final public void report(String msg, Throwable t) { - System.err.println(msg); - System.err.println("Reported exception:"); - t.printStackTrace(); - } - - static final public void report(String msg) { - System.err.println("SLF4J: " + msg); - } +// private static final void report(String msg, Throwable t) { +// System.err.println(msg); +// System.err.println("Reported exception:"); +// t.printStackTrace(); +// } +// +// static final private void report(String msg) { +// System.err.println("SLF4J: " + msg); +// } } diff --git a/slf4j-jdk-platform-logging/src/main/java/org/slf4j/jdk/platform/logging/SLF4JPlatformLogger.java b/slf4j-jdk-platform-logging/src/main/java/org/slf4j/jdk/platform/logging/SLF4JPlatformLogger.java index f2648baaa..194436d7e 100644 --- a/slf4j-jdk-platform-logging/src/main/java/org/slf4j/jdk/platform/logging/SLF4JPlatformLogger.java +++ b/slf4j-jdk-platform-logging/src/main/java/org/slf4j/jdk/platform/logging/SLF4JPlatformLogger.java @@ -31,6 +31,7 @@ import java.util.ResourceBundle; import org.slf4j.Logger; +import org.slf4j.helpers.Reporter; import org.slf4j.spi.CallerBoundaryAware; import org.slf4j.spi.LoggingEventBuilder; @@ -155,7 +156,7 @@ private void performLog(org.slf4j.event.Level slf4jLevel, ResourceBundle bundle, private void reportUnknownLevel(Level jplLevel) { String message = "Unknown log level [" + jplLevel + "]"; IllegalArgumentException iae = new IllegalArgumentException(message); - org.slf4j.helpers.Util.report("Unsupported log level", iae); + Reporter.error("Unsupported log level", iae); } private static String getResourceStringOrMessage(ResourceBundle bundle, String msg) { diff --git a/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerFactory.java b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerFactory.java index 4c4aadeb5..0aca814e7 100644 --- a/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerFactory.java +++ b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerFactory.java @@ -30,6 +30,7 @@ import org.apache.log4j.LogManager; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; +import org.slf4j.helpers.Reporter; import org.slf4j.helpers.Util; /** @@ -49,8 +50,8 @@ public class Reload4jLoggerFactory implements ILoggerFactory { String part1 = "Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. "; String part2 = "See also " + LOG4J_DELEGATION_LOOP_URL + " for more details."; - Util.report(part1); - Util.report(part2); + Reporter.error(part1); + Reporter.error(part2); throw new IllegalStateException(part1 + part2); } catch (ClassNotFoundException e) { // this is the good case diff --git a/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jServiceProvider.java b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jServiceProvider.java index 4625b09ca..ed023b31e 100644 --- a/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jServiceProvider.java +++ b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jServiceProvider.java @@ -4,6 +4,7 @@ import org.slf4j.ILoggerFactory; import org.slf4j.IMarkerFactory; import org.slf4j.helpers.BasicMarkerFactory; +import org.slf4j.helpers.Reporter; import org.slf4j.helpers.Util; import org.slf4j.spi.MDCAdapter; import org.slf4j.spi.SLF4JServiceProvider; @@ -26,7 +27,7 @@ public Reload4jServiceProvider() { @SuppressWarnings("unused") Level level = Level.TRACE; } catch (NoSuchFieldError nsfe) { - Util.report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version"); + Reporter.error("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version"); } } diff --git a/slf4j-simple/src/main/java/org/slf4j/simple/SimpleLoggerConfiguration.java b/slf4j-simple/src/main/java/org/slf4j/simple/SimpleLoggerConfiguration.java index fb9808d89..0a7f1310d 100755 --- a/slf4j-simple/src/main/java/org/slf4j/simple/SimpleLoggerConfiguration.java +++ b/slf4j-simple/src/main/java/org/slf4j/simple/SimpleLoggerConfiguration.java @@ -10,6 +10,7 @@ import java.text.SimpleDateFormat; import java.util.Properties; +import org.slf4j.helpers.Reporter; import org.slf4j.helpers.Util; import org.slf4j.simple.OutputChoice.OutputChoiceType; @@ -98,7 +99,7 @@ void init() { try { dateFormatter = new SimpleDateFormat(dateTimeFormatStr); } catch (IllegalArgumentException e) { - Util.report("Bad date format in " + CONFIGURATION_FILE + "; will output relative time", e); + Reporter.error("Bad date format in " + CONFIGURATION_FILE + "; will output relative time", e); } } } @@ -183,7 +184,7 @@ else if ("System.out".equalsIgnoreCase(logFile)) { PrintStream printStream = new PrintStream(fos); return new OutputChoice(printStream); } catch (FileNotFoundException e) { - Util.report("Could not open [" + logFile + "]. Defaulting to System.err", e); + Reporter.error("Could not open [" + logFile + "]. Defaulting to System.err", e); return new OutputChoice(OutputChoiceType.SYS_ERR); } }