mirror of https://github.com/qos-ch/slf4j
Merge remote-tracking branch 'origin' into slf4j-344-logServiceReader
Conflicts: osgi-over-slf4j/pom.xml
This commit is contained in:
commit
9bea50f144
|
|
@ -17,7 +17,6 @@
|
||||||
package org.apache.log4j;
|
package org.apache.log4j;
|
||||||
|
|
||||||
import org.apache.log4j.spi.LoggerFactory;
|
import org.apache.log4j.spi.LoggerFactory;
|
||||||
import org.slf4j.helpers.Util;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
@ -36,23 +35,6 @@ class Log4jLoggerFactory {
|
||||||
// String, Logger
|
// String, Logger
|
||||||
private static ConcurrentMap<String, Logger> log4jLoggers = new ConcurrentHashMap<String, Logger>();
|
private static ConcurrentMap<String, Logger> log4jLoggers = new ConcurrentHashMap<String, Logger>();
|
||||||
|
|
||||||
private static final String LOG4J_DELEGATION_LOOP_URL = "http://www.slf4j.org/codes.html#log4jDelegationLoop";
|
|
||||||
|
|
||||||
// check for delegation loops
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
Class.forName("org.slf4j.impl.Log4jLoggerFactory");
|
|
||||||
String part1 = "Detected both log4j-over-slf4j.jar AND 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);
|
|
||||||
throw new IllegalStateException(part1 + part2);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
// this is the good case
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Logger getLogger(String name) {
|
public static Logger getLogger(String name) {
|
||||||
org.apache.log4j.Logger instance = log4jLoggers.get(name);
|
org.apache.log4j.Logger instance = log4jLoggers.get(name);
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
Implementation-Title: osgi-over-slf4j
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Bundle-SymbolicName: org.slf4j.osgi-over-slf4j
|
||||||
|
Bundle-Name: OSGi LogService implemented over SLF4J
|
||||||
|
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||||
|
Bundle-Activator: org.slf4j.osgi.logservice.impl.Activator
|
||||||
|
Bundle-Category: osgi
|
||||||
|
Import-Package: org.osgi.framework;version="[1.5,2)",org.osgi.service.log;version="[1.3,2)",org.slf4j;version=${parsedVersion.osgiVersion}
|
||||||
|
|
@ -44,6 +44,15 @@ public class StaticMDCBinder {
|
||||||
private StaticMDCBinder() {
|
private StaticMDCBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMDCBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static final StaticMDCBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link NOPMDCAdapter}.
|
* {@link NOPMDCAdapter}.
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
||||||
private StaticMarkerBinder() {
|
private StaticMarkerBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMarkerBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static StaticMarkerBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link BasicMarkerFactory}.
|
* {@link BasicMarkerFactory}.
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ public final class LoggerFactory {
|
||||||
|
|
||||||
// Support for detecting mismatched logger names.
|
// Support for detecting mismatched logger names.
|
||||||
static final String DETECT_LOGGER_NAME_MISMATCH_PROPERTY = "slf4j.detectLoggerNameMismatch";
|
static final String DETECT_LOGGER_NAME_MISMATCH_PROPERTY = "slf4j.detectLoggerNameMismatch";
|
||||||
|
static final String JAVA_VENDOR_PROPERTY = "java.vendor.url";
|
||||||
|
|
||||||
static boolean DETECT_LOGGER_NAME_MISMATCH = Util.safeGetBooleanSystemProperty(DETECT_LOGGER_NAME_MISMATCH_PROPERTY);
|
static boolean DETECT_LOGGER_NAME_MISMATCH = Util.safeGetBooleanSystemProperty(DETECT_LOGGER_NAME_MISMATCH_PROPERTY);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -254,6 +256,11 @@ public final class LoggerFactory {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static void reportMultipleBindingAmbiguity(Set<URL> staticLoggerBinderPathSet) {
|
private static void reportMultipleBindingAmbiguity(Set<URL> staticLoggerBinderPathSet) {
|
||||||
|
if(isAndroid()) {
|
||||||
|
// skip check under android, see also http://jira.qos.ch/browse/SLF4J-328
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) {
|
if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) {
|
||||||
Util.report("Class path contains multiple SLF4J bindings.");
|
Util.report("Class path contains multiple SLF4J bindings.");
|
||||||
for (URL path : staticLoggerBinderPathSet) {
|
for (URL path : staticLoggerBinderPathSet) {
|
||||||
|
|
@ -263,6 +270,13 @@ 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(Set<URL> staticLoggerBinderPathSet) {
|
private static void reportActualBinding(Set<URL> staticLoggerBinderPathSet) {
|
||||||
if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) {
|
if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) {
|
||||||
Util.report("Actual binding is of type [" + StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr() + "]");
|
Util.report("Actual binding is of type [" + StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr() + "]");
|
||||||
|
|
|
||||||
|
|
@ -85,9 +85,27 @@ public class MDC {
|
||||||
private MDC() {
|
private MDC() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As of SLF4J version 1.7.14, StaticMDCBinder classes shipping in various bindings
|
||||||
|
* come with a getSingleton() method. Previously only a public field called SINGLETON
|
||||||
|
* was available.
|
||||||
|
*
|
||||||
|
* @return MDCAdapter
|
||||||
|
* @throws NoClassDefFoundError in case no binding is available
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
private static MDCAdapter bwCompatibleGetMDCAdapterFromBinder() throws NoClassDefFoundError {
|
||||||
|
try {
|
||||||
|
return StaticMDCBinder.getSingleton().getMDCA();
|
||||||
|
} catch (NoSuchMethodError nsme) {
|
||||||
|
// binding is probably a version of SLF4J older than 1.7.14
|
||||||
|
return StaticMDCBinder.SINGLETON.getMDCA();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
mdcAdapter = StaticMDCBinder.SINGLETON.getMDCA();
|
mdcAdapter = bwCompatibleGetMDCAdapterFromBinder();
|
||||||
} catch (NoClassDefFoundError ncde) {
|
} catch (NoClassDefFoundError ncde) {
|
||||||
mdcAdapter = new NOPMDCAdapter();
|
mdcAdapter = new NOPMDCAdapter();
|
||||||
String msg = ncde.getMessage();
|
String msg = ncde.getMessage();
|
||||||
|
|
|
||||||
|
|
@ -42,17 +42,35 @@ import org.slf4j.impl.StaticMarkerBinder;
|
||||||
* @author Ceki Gülcü
|
* @author Ceki Gülcü
|
||||||
*/
|
*/
|
||||||
public class MarkerFactory {
|
public class MarkerFactory {
|
||||||
static IMarkerFactory markerFactory;
|
static IMarkerFactory MARKER_FACTORY;
|
||||||
|
|
||||||
private MarkerFactory() {
|
private MarkerFactory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As of SLF4J version 1.7.14, StaticMarkerBinder classes shipping in various bindings
|
||||||
|
* come with a getSingleton() method. Previously only a public field called SINGLETON
|
||||||
|
* was available.
|
||||||
|
*
|
||||||
|
* @return IMarkerFactory
|
||||||
|
* @throws NoClassDefFoundError in case no binding is available
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
private static IMarkerFactory bwCompatibleGetMarkerFactoryFromBinder() throws NoClassDefFoundError {
|
||||||
|
try {
|
||||||
|
return StaticMarkerBinder.getSingleton().getMarkerFactory();
|
||||||
|
} catch (NoSuchMethodError nsme) {
|
||||||
|
// binding is probably a version of SLF4J older than 1.7.14
|
||||||
|
return StaticMarkerBinder.SINGLETON.getMarkerFactory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is where the binding happens
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
markerFactory = StaticMarkerBinder.SINGLETON.getMarkerFactory();
|
MARKER_FACTORY = bwCompatibleGetMarkerFactoryFromBinder();
|
||||||
} catch (NoClassDefFoundError e) {
|
} catch (NoClassDefFoundError e) {
|
||||||
markerFactory = new BasicMarkerFactory();
|
MARKER_FACTORY = new BasicMarkerFactory();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// we should never get here
|
// we should never get here
|
||||||
Util.report("Unexpected failure while binding MarkerFactory", e);
|
Util.report("Unexpected failure while binding MarkerFactory", e);
|
||||||
|
|
@ -68,7 +86,7 @@ public class MarkerFactory {
|
||||||
* @return marker
|
* @return marker
|
||||||
*/
|
*/
|
||||||
public static Marker getMarker(String name) {
|
public static Marker getMarker(String name) {
|
||||||
return markerFactory.getMarker(name);
|
return MARKER_FACTORY.getMarker(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -79,7 +97,7 @@ public class MarkerFactory {
|
||||||
* @since 1.5.1
|
* @since 1.5.1
|
||||||
*/
|
*/
|
||||||
public static Marker getDetachedMarker(String name) {
|
public static Marker getDetachedMarker(String name) {
|
||||||
return markerFactory.getDetachedMarker(name);
|
return MARKER_FACTORY.getDetachedMarker(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -91,6 +109,6 @@ public class MarkerFactory {
|
||||||
* @return the IMarkerFactory instance in use
|
* @return the IMarkerFactory instance in use
|
||||||
*/
|
*/
|
||||||
public static IMarkerFactory getIMarkerFactory() {
|
public static IMarkerFactory getIMarkerFactory() {
|
||||||
return markerFactory;
|
return MARKER_FACTORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -42,6 +42,16 @@ public class StaticMDCBinder {
|
||||||
private StaticMDCBinder() {
|
private StaticMDCBinder() {
|
||||||
throw new UnsupportedOperationException("This code should never make it into the jar");
|
throw new UnsupportedOperationException("This code should never make it into the jar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMDCBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static final StaticMDCBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
||||||
throw new UnsupportedOperationException("This code should never make it into the jar");
|
throw new UnsupportedOperationException("This code should never make it into the jar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMarkerBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static StaticMarkerBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link BasicMarkerFactory}.
|
* {@link BasicMarkerFactory}.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
package org.slf4j;
|
||||||
|
|
||||||
|
import java.util.concurrent.BrokenBarrierException;
|
||||||
|
import java.util.concurrent.CyclicBarrier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class demonstrates that threads accessing the STATE variable always see a consistent value.
|
||||||
|
*
|
||||||
|
* During ongoing initialization the observed value is either ONGOING_INITIALIZATION
|
||||||
|
* or one of {SUCCESS, FAILURE}.
|
||||||
|
*
|
||||||
|
* Post initialization the observed value is always one of {SUCCESS, FAILURE}.
|
||||||
|
*
|
||||||
|
* See also http://jira.qos.ch/browse/SLF4J-167
|
||||||
|
*
|
||||||
|
* @author ceki
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DoubleCheckedInt {
|
||||||
|
|
||||||
|
final static int THREAD_COUNT = 10 + Runtime.getRuntime().availableProcessors() * 2;
|
||||||
|
final static int UNINITIALIZED_STATE = 0;
|
||||||
|
final static int ONGOING_INITIALIZATION = 1;
|
||||||
|
final static int SUCCESS = 2;
|
||||||
|
final static int FAILURE = 3;
|
||||||
|
final static int NUMBER_OF_STATES = FAILURE + 1;
|
||||||
|
|
||||||
|
private static int STATE = UNINITIALIZED_STATE;
|
||||||
|
|
||||||
|
public static int getState() {
|
||||||
|
if (STATE == 0) {
|
||||||
|
synchronized (DoubleCheckedInt.class) {
|
||||||
|
if (STATE == UNINITIALIZED_STATE) {
|
||||||
|
STATE = ONGOING_INITIALIZATION;
|
||||||
|
long r = System.nanoTime();
|
||||||
|
try {
|
||||||
|
Thread.sleep(10);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
if (r % 2 == 0) {
|
||||||
|
STATE = SUCCESS;
|
||||||
|
} else {
|
||||||
|
STATE = FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void main(String[] args) throws InterruptedException, BrokenBarrierException {
|
||||||
|
StateAccessingThread[] preInitializationThreads = harness();
|
||||||
|
check(preInitializationThreads, false);
|
||||||
|
|
||||||
|
System.out.println("============");
|
||||||
|
StateAccessingThread[] postInitializationThreads = harness();
|
||||||
|
check(postInitializationThreads, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StateAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
|
||||||
|
StateAccessingThread[] threads = new StateAccessingThread[THREAD_COUNT];
|
||||||
|
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||||
|
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||||
|
threads[i] = new StateAccessingThread(barrier);
|
||||||
|
threads[i].start();
|
||||||
|
}
|
||||||
|
|
||||||
|
barrier.await();
|
||||||
|
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||||
|
threads[i].join();
|
||||||
|
}
|
||||||
|
return threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void check(StateAccessingThread[] threads, boolean postInit) {
|
||||||
|
|
||||||
|
int[] stateCount = getStateCount(threads);
|
||||||
|
printStateCount(stateCount);
|
||||||
|
|
||||||
|
if (stateCount[UNINITIALIZED_STATE] != 0) {
|
||||||
|
throw new IllegalStateException("getState() should never return a zero value");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stateCount[SUCCESS] != 0 && stateCount[FAILURE] != 0) {
|
||||||
|
throw new IllegalStateException("getState() should return consistent values");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postInit) {
|
||||||
|
if (stateCount[SUCCESS] != THREAD_COUNT && stateCount[FAILURE] != THREAD_COUNT) {
|
||||||
|
throw new IllegalStateException("getState() should return consistent values");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printStateCount(int[] stateCount) {
|
||||||
|
for (int i = 0; i < NUMBER_OF_STATES; i++) {
|
||||||
|
switch (i) {
|
||||||
|
case UNINITIALIZED_STATE:
|
||||||
|
System.out.println("UNINITIALIZED_STATE count: " + stateCount[i]);
|
||||||
|
break;
|
||||||
|
case ONGOING_INITIALIZATION:
|
||||||
|
System.out.println("ONGOING_INITIALIZATION count: " + stateCount[i]);
|
||||||
|
break;
|
||||||
|
case SUCCESS:
|
||||||
|
System.out.println("SUCCESS count: " + stateCount[i]);
|
||||||
|
break;
|
||||||
|
case FAILURE:
|
||||||
|
System.out.println("FAILURE count: " + stateCount[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] getStateCount(StateAccessingThread[] threads) {
|
||||||
|
int[] valCount = new int[NUMBER_OF_STATES];
|
||||||
|
for (int i = 0; i < threads.length; i++) {
|
||||||
|
int val = threads[i].state;
|
||||||
|
valCount[val] = valCount[val] + 1;
|
||||||
|
}
|
||||||
|
return valCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class StateAccessingThread extends Thread {
|
||||||
|
public int state = -1;
|
||||||
|
final CyclicBarrier barrier;
|
||||||
|
|
||||||
|
StateAccessingThread(CyclicBarrier barrier) {
|
||||||
|
this.barrier = barrier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
barrier.await();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
state = DoubleCheckedInt.getState();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -46,7 +46,7 @@ public class JCLLoggerFactory implements ILoggerFactory {
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
Class.forName("org.apache.commons.logging.impl.SLF4JLogFactory");
|
Class.forName("org.apache.commons.logging.impl.SLF4JLogFactory");
|
||||||
String part1 = "Detected both jcl-over-slf4j.jar AND slf4j-jcl.jar on the class path, preempting StackOverflowError. ";
|
String part1 = "Detected both jcl-over-slf4j.jar AND bound slf4j-jcl.jar on the class path, preempting StackOverflowError. ";
|
||||||
String part2 = "See also " + JCL_DELEGATION_LOOP_URL + " for more details.";
|
String part2 = "See also " + JCL_DELEGATION_LOOP_URL + " for more details.";
|
||||||
|
|
||||||
Util.report(part1);
|
Util.report(part1);
|
||||||
|
|
@ -58,7 +58,7 @@ public class JCLLoggerFactory implements ILoggerFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// key: name (String), value: a JCLLoggerAdapter;
|
// key: name (String), value: a JCLLoggerAdapter;
|
||||||
ConcurrentMap<String, Logger> loggerMap;
|
final ConcurrentMap<String, Logger> loggerMap;
|
||||||
|
|
||||||
public JCLLoggerFactory() {
|
public JCLLoggerFactory() {
|
||||||
loggerMap = new ConcurrentHashMap<String, Logger>();
|
loggerMap = new ConcurrentHashMap<String, Logger>();
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,22 @@ public class StaticMDCBinder {
|
||||||
private StaticMDCBinder() {
|
private StaticMDCBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMDCBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static final StaticMDCBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link NOPMDCAdapter}.
|
* {@link NOPMDCAdapter}.
|
||||||
*
|
*
|
||||||
* @return instance of NOPMDCAdapter
|
* @return instance of NOPMDCAdapter
|
||||||
|
* @since 1.7.14
|
||||||
*/
|
*/
|
||||||
public MDCAdapter getMDCA() {
|
public MDCAdapter getMDCA() {
|
||||||
return new NOPMDCAdapter();
|
return new NOPMDCAdapter();
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
||||||
private StaticMarkerBinder() {
|
private StaticMarkerBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMarkerBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static StaticMarkerBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link BasicMarkerFactory}.
|
* {@link BasicMarkerFactory}.
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,17 @@ public class StaticMDCBinder {
|
||||||
|
|
||||||
private StaticMDCBinder() {
|
private StaticMDCBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMDCBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static final StaticMDCBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link BasicMDCAdapter}.
|
* {@link BasicMDCAdapter}.
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
||||||
private StaticMarkerBinder() {
|
private StaticMarkerBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMarkerBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static StaticMarkerBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link BasicMarkerFactory}.
|
* {@link BasicMarkerFactory}.
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import org.apache.log4j.LogManager;
|
import org.apache.log4j.LogManager;
|
||||||
|
import org.slf4j.helpers.Util;
|
||||||
import org.slf4j.ILoggerFactory;
|
import org.slf4j.ILoggerFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
|
@ -39,6 +40,23 @@ import org.slf4j.Logger;
|
||||||
*/
|
*/
|
||||||
public class Log4jLoggerFactory implements ILoggerFactory {
|
public class Log4jLoggerFactory implements ILoggerFactory {
|
||||||
|
|
||||||
|
private static final String LOG4J_DELEGATION_LOOP_URL = "http://www.slf4j.org/codes.html#log4jDelegationLoop";
|
||||||
|
|
||||||
|
// check for delegation loops
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Class.forName("org.apache.log4j.Log4jLoggerFactory");
|
||||||
|
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);
|
||||||
|
throw new IllegalStateException(part1 + part2);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// this is the good case
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// key: name (String), value: a Log4jLoggerAdapter;
|
// key: name (String), value: a Log4jLoggerAdapter;
|
||||||
ConcurrentMap<String, Logger> loggerMap;
|
ConcurrentMap<String, Logger> loggerMap;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,17 @@ public class StaticMDCBinder {
|
||||||
|
|
||||||
private StaticMDCBinder() {
|
private StaticMDCBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMDCBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static final StaticMDCBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link StaticMDCBinder}.
|
* {@link StaticMDCBinder}.
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
||||||
private StaticMarkerBinder() {
|
private StaticMarkerBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMarkerBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static StaticMarkerBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link BasicMarkerFactory}.
|
* {@link BasicMarkerFactory}.
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,16 @@ public class StaticMDCBinder {
|
||||||
private StaticMDCBinder() {
|
private StaticMDCBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMDCBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static final StaticMDCBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link StaticMDCBinder}.
|
* {@link StaticMDCBinder}.
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
||||||
private StaticMarkerBinder() {
|
private StaticMarkerBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMarkerBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static StaticMarkerBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link BasicMarkerFactory}.
|
* {@link BasicMarkerFactory}.
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,16 @@ public class StaticMDCBinder {
|
||||||
private StaticMDCBinder() {
|
private StaticMDCBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMDCBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static final StaticMDCBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link StaticMDCBinder}.
|
* {@link StaticMDCBinder}.
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,17 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
||||||
|
|
||||||
private StaticMarkerBinder() {
|
private StaticMarkerBinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticMarkerBinder singleton
|
||||||
|
* @since 1.7.14
|
||||||
|
*/
|
||||||
|
public static StaticMarkerBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently this method always returns an instance of
|
* Currently this method always returns an instance of
|
||||||
* {@link BasicMarkerFactory}.
|
* {@link BasicMarkerFactory}.
|
||||||
|
|
|
||||||
|
|
@ -323,10 +323,11 @@ class B extends A {
|
||||||
<p>The purpose of slf4j-log4j12 module is to delegate or redirect
|
<p>The purpose of slf4j-log4j12 module is to delegate or redirect
|
||||||
calls made to an SLF4J logger to log4j. The purpose of the
|
calls made to an SLF4J logger to log4j. The purpose of the
|
||||||
log4j-over-slf4j module is to redirect calls made to a log4j
|
log4j-over-slf4j module is to redirect calls made to a log4j
|
||||||
logger to SLF4J. If both <em>slf4j-log4j12.jar</em> and
|
logger to SLF4J. If SLF4J is bound with<em>slf4j-log4j12.jar</em>
|
||||||
<em>log4j-over-slf4j.jar</em> are present on the class path, a
|
and <em>log4j-over-slf4j.jar</em> is also present on the class
|
||||||
<code>StackOverflowError</code> will inevitably occur immediately
|
path, a <code>StackOverflowError</code> will inevitably occur
|
||||||
after the first invocation of an SLF4J or a log4j logger.
|
immediately after the first invocation of an SLF4J or a log4j
|
||||||
|
logger.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>Here is how the exception might look like:</p>
|
<p>Here is how the exception might look like:</p>
|
||||||
|
|
@ -371,11 +372,11 @@ class B extends A {
|
||||||
<p>The purpose of slf4j-jcl module is to delegate or redirect
|
<p>The purpose of slf4j-jcl module is to delegate or redirect
|
||||||
calls made to an SLF4J logger to jakarta commons logging
|
calls made to an SLF4J logger to jakarta commons logging
|
||||||
(JCL). The purpose of the jcl-over-slf4j module is to redirect
|
(JCL). The purpose of the jcl-over-slf4j module is to redirect
|
||||||
calls made to a JCL logger to SLF4J. If both
|
calls made to a JCL logger to SLF4J. If SLF4J is bound with
|
||||||
<em>slf4j-jcl.jar</em> and <em>jcl-over-slf4j.jar</em> are present
|
<em>slf4j-jcl.jar</em> and <em>jcl-over-slf4j.jar</em> is also
|
||||||
on the class path, then a <code>StackOverflowError</code> will
|
present on the class path, then a <code>StackOverflowError</code>
|
||||||
inevitably occur immediately after the first invocation of an
|
will inevitably occur immediately after the first invocation of an
|
||||||
SLF4J or a JCL logger.
|
SLF4J or a JCL logger.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>Here is how the exception might look like:</p>
|
<p>Here is how the exception might look like:</p>
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,52 @@
|
||||||
|
|
||||||
<hr noshade="noshade" size="1"/>
|
<hr noshade="noshade" size="1"/>
|
||||||
|
|
||||||
|
<h3>xxx January, 2016 - Release of SLF4J 1.7.14</h3>
|
||||||
|
|
||||||
|
|
||||||
|
<p>The assignment of the INITIALIZATION_STATE variable in
|
||||||
|
<code>LoggerFactory</code> is now guaranteed to be consistent for
|
||||||
|
multi-thread initializations. More specifically, only one thread
|
||||||
|
will see INITIALIZATION_STATE as UNINITIALIZED with all other
|
||||||
|
threads observing either ONGOING_INITIALIZATION or the final result
|
||||||
|
of the initialization. However, SLF4J initialization is still
|
||||||
|
non-blocking and re-entrant, in the sense that if some thread tries
|
||||||
|
to obtain loggers during ongoing initialization by another (or
|
||||||
|
same) thread, instances of <code>SubstituteLogger</code> are
|
||||||
|
returned. This fixes <a
|
||||||
|
href="http://jira.qos.ch/browse/SLF4J-167">SLF4J-167</a> </p>.
|
||||||
|
|
||||||
|
|
||||||
|
<p>Moved delegation check loop from <em>log4j-over-slf4j.jar</em>
|
||||||
|
to <em>slf4j-log4j12.jar</em> for better targeted loop checks. The
|
||||||
|
rationale behind the change is explained by Frans Orsel in <a
|
||||||
|
href="http://jira.qos.ch/browse/SLF4J-345">SLF4J-345</a> who also
|
||||||
|
provided the relevant pull request.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>During initialization the binding ambiguity check is skipped
|
||||||
|
under Android in order to improve performance. This change was
|
||||||
|
requested by Nitin Verma in <a
|
||||||
|
href="http://jira.qos.ch/browse/SLF4J-328">SLF4J-328</a> who also
|
||||||
|
provided the relevant patch.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>The <code>StaticMarkerBinder</code> and
|
||||||
|
<code>StaticMDCBinder</code> classes shipping in various SLF4J
|
||||||
|
bindings now offer a <code>getSingletion()</code> method. The
|
||||||
|
<code>org.slf4j.MDC</code> and <code>MarkerFactory</code> classes
|
||||||
|
now perform binding by invoking the <code>getSingleton()</code>
|
||||||
|
method first and if in the presence of an older version of SLF4J
|
||||||
|
with said method missing, then by accessing the SINGLETON
|
||||||
|
field. This backward compatible change was requested by Rufus
|
||||||
|
Alexander in <a
|
||||||
|
href="http://jira.qos.ch/browse/SLF4J-347">SLF4J-347</a> in order
|
||||||
|
to implement an SLF4J binding in Clojure, namely <a
|
||||||
|
href="https://github.com/fzakaria/slf4j-timbre">slf4j-timbre</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<hr noshade="noshade" size="1"/>
|
||||||
|
|
||||||
<h3>10th of November, 2015 - Release of SLF4J 1.7.13</h3>
|
<h3>10th of November, 2015 - Release of SLF4J 1.7.13</h3>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue