mirror of https://github.com/qos-ch/slf4j
document 1.8 error messages
This commit is contained in:
parent
7b82bd29e4
commit
89e93009ea
|
|
@ -58,21 +58,32 @@ public class MissingSingletonMethodAssertionTest extends TestCase {
|
||||||
} catch (NoSuchMethodError e) {
|
} catch (NoSuchMethodError e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(String s: sps.stringList) {
|
||||||
|
System.out.println(s);
|
||||||
|
}
|
||||||
int lineCount = sps.stringList.size();
|
int lineCount = sps.stringList.size();
|
||||||
assertTrue("number of lines should be 3 but was " + lineCount, lineCount == 3);
|
assertTrue("number of lines should be 3 but was " + lineCount, lineCount == 3);
|
||||||
|
|
||||||
// expected output:
|
// expected output: (version 1.7 and earlier)
|
||||||
// SLF4J: slf4j-api 1.6.x (or later) is incompatible with this binding.
|
// SLF4J: slf4j-api 1.6.x (or later) is incompatible with this binding.
|
||||||
// SLF4J: Your binding is version 1.4.x or earlier.
|
// SLF4J: Your binding is version 1.4.x or earlier.
|
||||||
// SLF4J: Upgrade your binding to version 1.6.x. or 2.0.x
|
// SLF4J: Upgrade your binding to version 1.6.x. or 2.0.x
|
||||||
|
|
||||||
|
// expected output: (version 1.8)
|
||||||
|
// SLF4J: No SLF4J providers were found.
|
||||||
|
// SLF4J: Defaulting to no-operation (NOP) logger implementation
|
||||||
|
// SLF4J: See http://www.slf4j.org/codes.html#w for further details.
|
||||||
|
// SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions prior to 1.8.
|
||||||
|
// SLF4J: Ignoring binding found at [jar:file:/C:/home/ceki/slf4j/integration/lib/slf4j-simple-1.4.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
|
||||||
|
// SLF4J: See http://www.slf4j.org/codes.html#ignoredBindings for an explanation.
|
||||||
|
|
||||||
{
|
{
|
||||||
String s = (String) sps.stringList.get(0);
|
String s = (String) sps.stringList.get(0);
|
||||||
assertTrue(s.contains("SLF4J: slf4j-api 1.6.x (or later) is incompatible with this binding."));
|
assertTrue(s.contains("No SLF4J providers were found."));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
String s = (String) sps.stringList.get(1);
|
String s = (String) sps.stringList.get(1);
|
||||||
assertTrue(s.contains("SLF4J: Your binding is version 1.5.5 or earlier."));
|
assertTrue(s.contains("Defaulting to no-operation (NOP) logger implementation"));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
String s = (String) sps.stringList.get(2);
|
String s = (String) sps.stringList.get(2);
|
||||||
|
|
|
||||||
|
|
@ -24,19 +24,22 @@
|
||||||
*/
|
*/
|
||||||
package org.slf4j;
|
package org.slf4j;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
import org.slf4j.event.SubstituteLoggingEvent;
|
import org.slf4j.event.SubstituteLoggingEvent;
|
||||||
import org.slf4j.helpers.NOPLoggerFactory;
|
import org.slf4j.helpers.NOPServiceProvider;
|
||||||
import org.slf4j.helpers.SubstitureServiceProvider;
|
import org.slf4j.helpers.SubstitureServiceProvider;
|
||||||
import org.slf4j.helpers.SubstituteLogger;
|
import org.slf4j.helpers.SubstituteLogger;
|
||||||
import org.slf4j.helpers.SubstituteLoggerFactory;
|
|
||||||
import org.slf4j.helpers.Util;
|
import org.slf4j.helpers.Util;
|
||||||
import org.slf4j.helpers.NOPServiceProvider;
|
|
||||||
import org.slf4j.spi.SLF4JServiceProvider;
|
import org.slf4j.spi.SLF4JServiceProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -63,6 +66,9 @@ public final class LoggerFactory {
|
||||||
|
|
||||||
static final String CODES_PREFIX = "http://www.slf4j.org/codes.html";
|
static final String CODES_PREFIX = "http://www.slf4j.org/codes.html";
|
||||||
|
|
||||||
|
static final String NO_PROVIDERS_URL = CODES_PREFIX + "#noProviders";
|
||||||
|
static final String IGNORED_BINDINGS_URL = CODES_PREFIX + "#ignoredBindings";
|
||||||
|
|
||||||
static final String NO_STATICLOGGERBINDER_URL = CODES_PREFIX + "#StaticLoggerBinder";
|
static final String NO_STATICLOGGERBINDER_URL = CODES_PREFIX + "#StaticLoggerBinder";
|
||||||
static final String MULTIPLE_BINDINGS_URL = CODES_PREFIX + "#multiple_bindings";
|
static final String MULTIPLE_BINDINGS_URL = CODES_PREFIX + "#multiple_bindings";
|
||||||
static final String NULL_LF_URL = CODES_PREFIX + "#null_LF";
|
static final String NULL_LF_URL = CODES_PREFIX + "#null_LF";
|
||||||
|
|
@ -139,13 +145,8 @@ public final class LoggerFactory {
|
||||||
|
|
||||||
private final static void bind() {
|
private final static void bind() {
|
||||||
try {
|
try {
|
||||||
List<SLF4JServiceProvider> providersList = null;
|
List<SLF4JServiceProvider> providersList = findServiceProviders();
|
||||||
// skip check under android, see also
|
reportMultipleBindingAmbiguity(providersList);
|
||||||
// http://jira.qos.ch/browse/SLF4J-328
|
|
||||||
if (!isAndroid()) {
|
|
||||||
providersList = findServiceProviders();
|
|
||||||
reportMultipleBindingAmbiguity(providersList);
|
|
||||||
}
|
|
||||||
if (providersList != null && !providersList.isEmpty()) {
|
if (providersList != null && !providersList.isEmpty()) {
|
||||||
PROVIDER = providersList.get(0);
|
PROVIDER = providersList.get(0);
|
||||||
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
|
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
|
||||||
|
|
@ -156,7 +157,12 @@ public final class LoggerFactory {
|
||||||
SUBST_PROVIDER.getSubstituteLoggerFactory().clear();
|
SUBST_PROVIDER.getSubstituteLoggerFactory().clear();
|
||||||
} else {
|
} else {
|
||||||
INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
|
INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
|
||||||
Util.report("No providers could be found.");
|
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.");
|
||||||
|
|
||||||
|
Set<URL> staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
|
||||||
|
reportIgnoredStaticLoggerBinders(staticLoggerBinderPathSet);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
failedBinding(e);
|
failedBinding(e);
|
||||||
|
|
@ -164,6 +170,46 @@ public final class LoggerFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void reportIgnoredStaticLoggerBinders(Set<URL> staticLoggerBinderPathSet) {
|
||||||
|
if (staticLoggerBinderPathSet.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Util.report("Class path contains SLF4J bindings targeting slf4j-api versions prior to 1.8.");
|
||||||
|
for (URL path : staticLoggerBinderPathSet) {
|
||||||
|
Util.report("Ignoring binding found at [" + path + "]");
|
||||||
|
}
|
||||||
|
Util.report("See " + IGNORED_BINDINGS_URL + " for an explanation.");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to use the name of the StaticLoggerBinder class, but we can't
|
||||||
|
// reference the class itself.
|
||||||
|
private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";
|
||||||
|
|
||||||
|
static Set<URL> findPossibleStaticLoggerBinderPathSet() {
|
||||||
|
// use Set instead of list in order to deal with bug #138
|
||||||
|
// LinkedHashSet appropriate here because it preserves insertion order
|
||||||
|
// during iteration
|
||||||
|
Set<URL> staticLoggerBinderPathSet = new LinkedHashSet<URL>();
|
||||||
|
try {
|
||||||
|
ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader();
|
||||||
|
Enumeration<URL> paths;
|
||||||
|
if (loggerFactoryClassLoader == null) {
|
||||||
|
paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
|
||||||
|
} else {
|
||||||
|
paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH);
|
||||||
|
}
|
||||||
|
while (paths.hasMoreElements()) {
|
||||||
|
URL path = paths.nextElement();
|
||||||
|
staticLoggerBinderPathSet.add(path);
|
||||||
|
}
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Util.report("Error getting resources from path", ioe);
|
||||||
|
}
|
||||||
|
return staticLoggerBinderPathSet;
|
||||||
|
}
|
||||||
|
|
||||||
private static void fixSubstituteLoggers() {
|
private static void fixSubstituteLoggers() {
|
||||||
synchronized (SUBST_PROVIDER) {
|
synchronized (SUBST_PROVIDER) {
|
||||||
SUBST_PROVIDER.getSubstituteLoggerFactory().postInitialization();
|
SUBST_PROVIDER.getSubstituteLoggerFactory().postInitialization();
|
||||||
|
|
@ -279,7 +325,7 @@ public final class LoggerFactory {
|
||||||
*/
|
*/
|
||||||
private static void reportMultipleBindingAmbiguity(List<SLF4JServiceProvider> providerList) {
|
private static void reportMultipleBindingAmbiguity(List<SLF4JServiceProvider> providerList) {
|
||||||
if (isAmbiguousProviderList(providerList)) {
|
if (isAmbiguousProviderList(providerList)) {
|
||||||
Util.report("Class path contains multiple SLF4J bindings.");
|
Util.report("Class path contains multiple SLF4J providers.");
|
||||||
for (SLF4JServiceProvider provider : providerList) {
|
for (SLF4JServiceProvider provider : providerList) {
|
||||||
Util.report("Found provider [" + provider + "]");
|
Util.report("Found provider [" + provider + "]");
|
||||||
}
|
}
|
||||||
|
|
@ -287,13 +333,6 @@ public final class LoggerFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isAndroid() {
|
|
||||||
String vendor = Util.safeGetSystemProperty(JAVA_VENDOR_PROPERTY);
|
|
||||||
if (vendor == null)
|
|
||||||
return false;
|
|
||||||
return vendor.toLowerCase().contains("android");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void reportActualBinding(List<SLF4JServiceProvider> providerList) {
|
private static void reportActualBinding(List<SLF4JServiceProvider> providerList) {
|
||||||
// binderPathSet can be null under Android
|
// binderPathSet can be null under Android
|
||||||
if (!providerList.isEmpty() && isAmbiguousProviderList(providerList)) {
|
if (!providerList.isEmpty() && isAmbiguousProviderList(providerList)) {
|
||||||
|
|
@ -364,7 +403,7 @@ public final class LoggerFactory {
|
||||||
return getProvider().getLoggerFactory();
|
return getProvider().getLoggerFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLF4JServiceProvider getProvider() {
|
static SLF4JServiceProvider getProvider() {
|
||||||
if (INITIALIZATION_STATE == UNINITIALIZED) {
|
if (INITIALIZATION_STATE == UNINITIALIZED) {
|
||||||
synchronized (LoggerFactory.class) {
|
synchronized (LoggerFactory.class) {
|
||||||
if (INITIALIZATION_STATE == UNINITIALIZED) {
|
if (INITIALIZATION_STATE == UNINITIALIZED) {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,59 @@
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ====================================================== -->
|
||||||
|
|
||||||
|
<h3 class="doAnchor" name="noProviders">No SLF4J providers
|
||||||
|
were found.
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>This <b>warning</b>, i.e. not an error, message is repoted when
|
||||||
|
no SLF4J providers could be found on the class path. Placing one
|
||||||
|
(and only one) of <em>slf4j-nop.jar</em>
|
||||||
|
<em>slf4j-simple.jar</em>, <em>slf4j-log4j12.jar</em>,
|
||||||
|
<em>slf4j-jdk14.jar</em> or <em>logback-classic.jar</em> on the
|
||||||
|
class path should solve the problem. Note that these providers
|
||||||
|
must target slf4j-api 1.8 or later.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>In the absence of a provider, SLF4J will default to a
|
||||||
|
no-operation (NOP) logger provider.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Please note that slf4j-api version 1.8.x and later use the <a
|
||||||
|
href="https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html">ServiceLoader</a>
|
||||||
|
mechanism. <span class="red">Earlier versions relied on the static
|
||||||
|
binder mechanism which is no loger supported.</span></p>
|
||||||
|
|
||||||
|
<p>If you are responsible for packaging an application and do not
|
||||||
|
care about logging, then placing <em>slf4j-nop.jar</em> on the
|
||||||
|
class path of your application will get rid of this warning
|
||||||
|
message. Note that embedded components such as libraries or
|
||||||
|
frameworks should not declare a dependency on any SLF4J providers
|
||||||
|
but only depend on slf4j-api. When a library declares a
|
||||||
|
compile-time dependency on a SLF4J provider, it imposes that
|
||||||
|
provider on the end-user, thus negating SLF4J's purpose. </p>
|
||||||
|
|
||||||
|
<!-- ====================================================== -->
|
||||||
|
|
||||||
|
<h3 class="doAnchor" name="ignoredBindings">Class path contains
|
||||||
|
SLF4J bindings targeting slf4j-api versions prior to 1.8
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>Planning for the advent of Jigsaw (Java 9), slf4j-api version
|
||||||
|
1.8.x and later use the <a
|
||||||
|
href="https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html">ServiceLoader</a>
|
||||||
|
mechanism. <span class="red">Earlier versions of SLF4J relied on
|
||||||
|
the static binder mechanism which is no loger
|
||||||
|
supported.</span></p>
|
||||||
|
|
||||||
|
<p>In case SLF4J finds no providers targeting SLF4J 1.8 but finds
|
||||||
|
instead bindings targeting SLF4J 1.7 or earlier, it will list the
|
||||||
|
bindings it finds but <b>ignores</b>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ====================================================== -->
|
||||||
|
|
||||||
<h3 class="doAnchor"
|
<h3 class="doAnchor"
|
||||||
name="unsuccessfulInit">IllegalStateException:
|
name="unsuccessfulInit">IllegalStateException:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue