mirror of https://github.com/qos-ch/slf4j
testing SLF4J-353 support
This commit is contained in:
parent
c3751df9af
commit
2d4074c65a
|
|
@ -56,7 +56,7 @@
|
|||
<pathelement location="../slf4j-simple/target/slf4j-simple-${currentVersion}.jar" />
|
||||
</path >
|
||||
|
||||
|
||||
|
||||
<path id="incompatibleMultiBinding">
|
||||
<pathelement location="target/test-classes/" />
|
||||
<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
|
||||
|
|
@ -103,7 +103,7 @@
|
|||
|
||||
<target name="testAll" depends="init,
|
||||
testMissingSingletonMethod,
|
||||
testMismatch,
|
||||
testMismatch,
|
||||
testMatch,
|
||||
testMultiBinding,
|
||||
testIncompatibleMultiBinding,
|
||||
|
|
@ -132,6 +132,19 @@
|
|||
|
||||
</target>
|
||||
|
||||
|
||||
<target name="testMixed17">
|
||||
|
||||
<junit printsummary="yes" fork="no" haltonfailure="yes">
|
||||
<classpath refid="pathMixed17" />
|
||||
<formatter type="plain" />
|
||||
<test fork="yes" todir="target/unit-reports"
|
||||
outfile="TEST-MIXED-17"
|
||||
name="org.slf4j.VersionMismatchAssertionTest" />
|
||||
</junit>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="testMismatch">
|
||||
|
||||
<junit printsummary="yes" fork="no" haltonfailure="yes">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2004-2011 QOS.ch
|
||||
* Copyright (c) 2004-2016 QOS.ch
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
|
|
|||
5
pom.xml
5
pom.xml
|
|
@ -182,9 +182,10 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.10</version>
|
||||
<version>2.19.1</version>
|
||||
<configuration>
|
||||
<forkMode>once</forkMode>
|
||||
<forkCount>2</forkCount>
|
||||
<reuseForks>false</reuseForks>
|
||||
<reportFormat>plain</reportFormat>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
<excludes>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ import java.util.LinkedHashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.event.LoggingEventAware;
|
||||
import org.slf4j.event.SubstituteLoggingEvent;
|
||||
import org.slf4j.helpers.NOPLoggerFactory;
|
||||
import org.slf4j.helpers.SubstituteLogger;
|
||||
|
|
@ -70,6 +69,7 @@ public final class LoggerFactory {
|
|||
static final String VERSION_MISMATCH = CODES_PREFIX + "#version_mismatch";
|
||||
static final String SUBSTITUTE_LOGGER_URL = CODES_PREFIX + "#substituteLogger";
|
||||
static final String LOGGER_NAME_MISMATCH_URL = CODES_PREFIX + "#loggerNameMismatch";
|
||||
static final String REPLAY_URL = CODES_PREFIX + "#replay";
|
||||
|
||||
static final String UNSUCCESSFUL_INIT_URL = CODES_PREFIX + "#unsuccessfulInit";
|
||||
static final String UNSUCCESSFUL_INIT_MSG = "org.slf4j.LoggerFactory could not be successfully initialized. See also " + UNSUCCESSFUL_INIT_URL;
|
||||
|
|
@ -116,7 +116,6 @@ public final class LoggerFactory {
|
|||
*/
|
||||
static void reset() {
|
||||
INITIALIZATION_STATE = UNINITIALIZED;
|
||||
SUBST_FACTORY = new SubstituteLoggerFactory();
|
||||
}
|
||||
|
||||
private final static void performInitialization() {
|
||||
|
|
@ -146,6 +145,7 @@ public final class LoggerFactory {
|
|||
reportActualBinding(staticLoggerBinderPathSet);
|
||||
fixSubstitutedLoggers();
|
||||
playRecordedEvents();
|
||||
SUBST_FACTORY.clear();
|
||||
} catch (NoClassDefFoundError ncde) {
|
||||
String msg = ncde.getMessage();
|
||||
if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
|
||||
|
|
@ -180,10 +180,21 @@ public final class LoggerFactory {
|
|||
private static void playRecordedEvents() {
|
||||
List<SubstituteLoggingEvent> events = SUBST_FACTORY.getEventList();
|
||||
|
||||
for (SubstituteLoggingEvent event : events) {
|
||||
if (events.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < events.size(); i++) {
|
||||
SubstituteLoggingEvent event = events.get(i);
|
||||
SubstituteLogger substLogger = event.getLogger();
|
||||
if (substLogger.isDelegateEventAware()) {
|
||||
if (i == 0)
|
||||
emitReplayWarning(events.size());
|
||||
substLogger.log(event);
|
||||
} else {
|
||||
if(i == 0)
|
||||
emitSubstitutionWarning();
|
||||
Util.report(substLogger.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -195,25 +206,10 @@ public final class LoggerFactory {
|
|||
return;
|
||||
}
|
||||
|
||||
boolean substitutionWarningEmmitted = false;
|
||||
for (SubstituteLogger subLogger : loggers) {
|
||||
Logger logger = getLogger(subLogger.getName());
|
||||
subLogger.setDelegate(logger);
|
||||
|
||||
if (!isEventAware(logger)) {
|
||||
if (!substitutionWarningEmmitted) {
|
||||
emitSubstitutionWarning();
|
||||
substitutionWarningEmmitted = true;
|
||||
}
|
||||
Util.report(subLogger.getName());
|
||||
}
|
||||
}
|
||||
|
||||
SUBST_FACTORY.clear();
|
||||
}
|
||||
|
||||
private static boolean isEventAware(Logger logger) {
|
||||
return logger instanceof LoggingEventAware;
|
||||
}
|
||||
|
||||
private static void emitSubstitutionWarning() {
|
||||
|
|
@ -224,6 +220,12 @@ public final class LoggerFactory {
|
|||
Util.report("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 suject to the filtering rules of the underlying logging system.");
|
||||
Util.report("See also " + REPLAY_URL);
|
||||
}
|
||||
|
||||
private final static void versionSanityCheck() {
|
||||
try {
|
||||
String requested = StaticLoggerBinder.REQUESTED_API_VERSION;
|
||||
|
|
@ -375,6 +377,7 @@ public final class LoggerFactory {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (INITIALIZATION_STATE) {
|
||||
case SUCCESSFUL_INITIALIZATION:
|
||||
return StaticLoggerBinder.getSingleton().getLoggerFactory();
|
||||
|
|
|
|||
|
|
@ -4,14 +4,17 @@ import java.util.List;
|
|||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.helpers.SubstituteLogger;
|
||||
|
||||
public class EventRecodingLogger implements Logger {
|
||||
|
||||
String name;
|
||||
SubstituteLogger logger;
|
||||
List<SubstituteLoggingEvent> eventList;
|
||||
|
||||
public EventRecodingLogger(String name, List<SubstituteLoggingEvent> eventList) {
|
||||
this.name = name;
|
||||
public EventRecodingLogger(SubstituteLogger logger, List<SubstituteLoggingEvent> eventList) {
|
||||
this.logger = logger;
|
||||
this.name = logger.getName();
|
||||
this.eventList = eventList;
|
||||
}
|
||||
|
||||
|
|
@ -24,9 +27,14 @@ public class EventRecodingLogger implements Logger {
|
|||
}
|
||||
|
||||
private void recordEvent(Level level, Marker marker, String msg, Object[] args, Throwable throwable) {
|
||||
//System.out.println("recording logger:"+name+", msg:"+msg);
|
||||
SubstituteLoggingEvent loggingEvent = new SubstituteLoggingEvent();
|
||||
loggingEvent.setTimeStamp(System.currentTimeMillis());
|
||||
loggingEvent.setLevel(level);
|
||||
loggingEvent.setLogger(logger);
|
||||
loggingEvent.setLoggerName(name);
|
||||
|
||||
|
||||
loggingEvent.setMessage(msg);
|
||||
loggingEvent.setArgumentArray(args);
|
||||
loggingEvent.setThrowable(throwable);
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
package org.slf4j.event;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ceki Gulcu
|
||||
* @since 1.7.15
|
||||
*/
|
||||
public interface LoggingEventAware {
|
||||
void log(LoggingEvent event);
|
||||
}
|
||||
|
|
@ -24,11 +24,12 @@
|
|||
*/
|
||||
package org.slf4j.helpers;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.event.LoggingEventAware;
|
||||
import org.slf4j.event.EventRecodingLogger;
|
||||
import org.slf4j.event.LoggingEvent;
|
||||
import org.slf4j.event.SubstituteLoggingEvent;
|
||||
|
|
@ -43,13 +44,15 @@ import org.slf4j.event.SubstituteLoggingEvent;
|
|||
* @author Chetan Mehrotra
|
||||
* @author Ceki Gulcu
|
||||
*/
|
||||
public class SubstituteLogger implements Logger, LoggingEventAware {
|
||||
public class SubstituteLogger implements Logger {
|
||||
|
||||
private final String name;
|
||||
|
||||
private volatile Logger _delegate;
|
||||
List<SubstituteLoggingEvent> eventList;
|
||||
private EventRecodingLogger eventRecodingLogger;
|
||||
|
||||
List<SubstituteLoggingEvent> eventList;
|
||||
|
||||
public SubstituteLogger(String name, List<SubstituteLoggingEvent> eventList) {
|
||||
this.name = name;
|
||||
this.eventList = eventList;
|
||||
|
|
@ -324,11 +327,15 @@ public class SubstituteLogger implements Logger, LoggingEventAware {
|
|||
* instance.
|
||||
*/
|
||||
Logger delegate() {
|
||||
return _delegate != null ? _delegate : makeEventRecodingLogger();
|
||||
return _delegate != null ? _delegate : getEventRecordingLogger();
|
||||
}
|
||||
|
||||
private EventRecodingLogger makeEventRecodingLogger() {
|
||||
return new EventRecodingLogger(name, eventList);
|
||||
|
||||
|
||||
private Logger getEventRecordingLogger() {
|
||||
if(eventRecodingLogger == null) {
|
||||
eventRecodingLogger = new EventRecodingLogger(this, eventList);
|
||||
}
|
||||
return eventRecodingLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -339,14 +346,30 @@ public class SubstituteLogger implements Logger, LoggingEventAware {
|
|||
this._delegate = delegate;
|
||||
}
|
||||
|
||||
Boolean delegateEventAware;
|
||||
Method logMethodCache;
|
||||
|
||||
public boolean isDelegateEventAware() {
|
||||
return (_delegate instanceof LoggingEventAware);
|
||||
}
|
||||
|
||||
public void log(LoggingEvent event) {
|
||||
if(_delegate instanceof LoggingEventAware) {
|
||||
LoggingEventAware eventLogger = (LoggingEventAware) _delegate;
|
||||
eventLogger.log(event);
|
||||
if (delegateEventAware != null)
|
||||
return delegateEventAware;
|
||||
|
||||
try {
|
||||
logMethodCache = _delegate.getClass().getMethod("log", LoggingEvent.class);
|
||||
delegateEventAware = Boolean.TRUE;
|
||||
} catch (NoSuchMethodException e) {
|
||||
delegateEventAware = Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
return delegateEventAware;
|
||||
}
|
||||
|
||||
public void log(LoggingEvent event) {
|
||||
if (isDelegateEventAware()) {
|
||||
try {
|
||||
logMethodCache.invoke(_delegate, event);
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (InvocationTargetException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,5 +71,6 @@ public class SubstituteLoggerFactory implements ILoggerFactory {
|
|||
|
||||
public void clear() {
|
||||
loggers.clear();
|
||||
eventList.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.Marker;
|
||||
import org.slf4j.event.EventConstants;
|
||||
import org.slf4j.event.LoggingEvent;
|
||||
import org.slf4j.event.LoggingEventAware;
|
||||
import org.slf4j.helpers.FormattingTuple;
|
||||
import org.slf4j.helpers.MarkerIgnoringBase;
|
||||
import org.slf4j.helpers.MessageFormatter;
|
||||
|
|
@ -46,7 +45,7 @@ import org.slf4j.spi.LocationAwareLogger;
|
|||
* @author Ceki Gülcü
|
||||
* @author Peter Royal
|
||||
*/
|
||||
public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements LocationAwareLogger, LoggingEventAware {
|
||||
public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements LocationAwareLogger {
|
||||
|
||||
private static final long serialVersionUID = -8053026990503422791L;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package org.slf4j;
|
||||
|
||||
public class LoggerFactoryFriend {
|
||||
static public void reset() {
|
||||
LoggerFactory.reset();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
* Copyright (c) 2004-2016 QOS.ch
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package org.slf4j.impl;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MultithreadedInitializationTest {
|
||||
|
||||
|
||||
final static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
|
||||
|
||||
private static AtomicLong EVENT_COUNT = new AtomicLong(0);
|
||||
|
||||
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
|
||||
|
||||
int diff = new Random().nextInt(10000);
|
||||
String loggerName = "org.slf4j.impl.MultithreadedInitializationTest";
|
||||
|
||||
private static java.util.logging.Logger getRootLogger() {
|
||||
return LogManager.getLogManager().getLogger("");
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
java.util.logging.Logger rootLogger = getRootLogger();
|
||||
Handler[] handlers = rootLogger.getHandlers();
|
||||
for (int i = 0; i < handlers.length; i++) {
|
||||
if (handlers[i] instanceof RecordingHandler) {
|
||||
rootLogger.removeHandler(handlers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void addRecordingHandler() {
|
||||
getRootLogger().addHandler(new RecordingHandler());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException {
|
||||
System.out.println("THREAD_COUNT=" + THREAD_COUNT);
|
||||
LoggerAccessingThread[] accessors = harness();
|
||||
|
||||
for (LoggerAccessingThread accessor : accessors) {
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
accessor.logger.info("post harness");
|
||||
}
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(loggerName + ".slowInitialization-" + diff);
|
||||
logger.info("hello");
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
|
||||
List<LogRecord> records = getRecordedEvents();
|
||||
assertEquals(EVENT_COUNT.get(), records.size());
|
||||
}
|
||||
|
||||
private List<LogRecord> getRecordedEvents() {
|
||||
RecordingHandler ra = findRecordingHandler();
|
||||
if(ra == null) {
|
||||
fail("failed to fing RecordingHandler");
|
||||
}
|
||||
return ra.records;
|
||||
}
|
||||
|
||||
RecordingHandler findRecordingHandler() {
|
||||
java.util.logging.Logger root = LogManager.getLogManager().getLogger("");
|
||||
Handler[] handlers = root.getHandlers();
|
||||
for (Handler h : handlers) {
|
||||
if (h instanceof RecordingHandler)
|
||||
return (RecordingHandler) h;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
|
||||
LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT];
|
||||
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i] = new LoggerAccessingThread(barrier, i);
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
barrier.await();
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
return threads;
|
||||
}
|
||||
|
||||
static class LoggerAccessingThread extends Thread {
|
||||
final CyclicBarrier barrier;
|
||||
Logger logger;
|
||||
int count;
|
||||
|
||||
LoggerAccessingThread(CyclicBarrier barrier, int count) {
|
||||
this.barrier = barrier;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
barrier.await();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
logger = LoggerFactory.getLogger(this.getClass().getName() + "-" + count);
|
||||
logger.info("in run method");
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package org.slf4j.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
public class RecordingHandler extends Handler {
|
||||
|
||||
List<LogRecord> records = new ArrayList<LogRecord>();
|
||||
|
||||
@Override
|
||||
public void publish(LogRecord record) {
|
||||
records.add(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -28,16 +28,12 @@ import static org.slf4j.event.EventConstants.NA_SUBST;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.log4j.Category;
|
||||
import org.apache.log4j.Level;
|
||||
import org.apache.log4j.Priority;
|
||||
import org.apache.log4j.spi.LocationInfo;
|
||||
import org.apache.log4j.spi.ThrowableInformation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.event.EventConstants;
|
||||
import org.slf4j.event.LoggingEvent;
|
||||
import org.slf4j.event.LoggingEventAware;
|
||||
import org.slf4j.helpers.FormattingTuple;
|
||||
import org.slf4j.helpers.MarkerIgnoringBase;
|
||||
import org.slf4j.helpers.MessageFormatter;
|
||||
|
|
@ -61,7 +57,7 @@ import org.slf4j.spi.LocationAwareLogger;
|
|||
*
|
||||
* @author Ceki Gülcü
|
||||
*/
|
||||
public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements LocationAwareLogger, LoggingEventAware, Serializable {
|
||||
public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements LocationAwareLogger, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6182834493563598289L;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* Copyright (c) 2004-2011 QOS.ch
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package org.slf4j.impl;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.apache.log4j.LogManager;
|
||||
import org.apache.log4j.spi.LoggingEvent;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MultithreadedInitializationTest {
|
||||
|
||||
// value of LogManager.DEFAULT_CONFIGURATION_KEY;
|
||||
static String CONFIG_FILE_KEY = "log4j.configuration";
|
||||
|
||||
final static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
|
||||
|
||||
private static AtomicLong EVENT_COUNT = new AtomicLong(0);
|
||||
|
||||
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
|
||||
int diff = new Random().nextInt(10000);
|
||||
String loggerName = "org.slf4j.impl.RecursiveInitializationTest";
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
System.clearProperty(CONFIG_FILE_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException {
|
||||
System.out.println("THREAD_COUNT=" + THREAD_COUNT);
|
||||
System.setProperty(CONFIG_FILE_KEY, "recursiveInitWithActivationDelay.properties");
|
||||
LoggerAccessingThread[] accessors = harness();
|
||||
|
||||
for (LoggerAccessingThread accessor : accessors) {
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
accessor.logger.info("post harness");
|
||||
}
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(loggerName + ".slowInitialization-" + diff);
|
||||
logger.info("hello");
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
|
||||
List<LoggingEvent> events = getRecordedEvents();
|
||||
assertEquals(EVENT_COUNT.get(), events.size());
|
||||
}
|
||||
|
||||
private List<LoggingEvent> getRecordedEvents() {
|
||||
org.apache.log4j.Logger root = LogManager.getRootLogger();
|
||||
|
||||
RecursiveAppender ra = (RecursiveAppender) root.getAppender("RECURSIVE");
|
||||
return ra.events;
|
||||
}
|
||||
|
||||
private static LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
|
||||
LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT];
|
||||
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i] = new LoggerAccessingThread(barrier, i);
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
barrier.await();
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
return threads;
|
||||
}
|
||||
|
||||
static class LoggerAccessingThread extends Thread {
|
||||
final CyclicBarrier barrier;
|
||||
Logger logger;
|
||||
int count;
|
||||
|
||||
LoggerAccessingThread(CyclicBarrier barrier, int count) {
|
||||
this.barrier = barrier;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
barrier.await();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
logger = LoggerFactory.getLogger(this.getClass().getName()+"-"+count);
|
||||
logger.info("in run method");
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -24,6 +24,8 @@
|
|||
*/
|
||||
package org.slf4j.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.log4j.AppenderSkeleton;
|
||||
|
|
@ -34,15 +36,20 @@ import org.slf4j.LoggerFactory;
|
|||
public class RecursiveAppender extends AppenderSkeleton {
|
||||
|
||||
int diff = new Random().nextInt();
|
||||
|
||||
int activationDelay = 0;
|
||||
String loggerName = "org.slf4j.impl.RecursiveAppender" + diff;
|
||||
|
||||
List<LoggingEvent> events = new ArrayList<LoggingEvent>();
|
||||
|
||||
public RecursiveAppender() {
|
||||
System.out.println("in RecursiveAppender constructor");
|
||||
Logger logger = LoggerFactory.getLogger("RecursiveAppender" + diff);
|
||||
System.out.println("logger class=" + logger.getClass().getName());
|
||||
System.out.println("entering RecursiveAppender constructor");
|
||||
Logger logger = LoggerFactory.getLogger(loggerName);
|
||||
logger.info("Calling a logger in the constructor");
|
||||
System.out.println("exiting RecursiveAppender constructor");
|
||||
}
|
||||
|
||||
protected void append(LoggingEvent arg0) {
|
||||
protected void append(LoggingEvent e) {
|
||||
events.add(e);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
|
|
@ -51,4 +58,32 @@ public class RecursiveAppender extends AppenderSkeleton {
|
|||
public boolean requiresLayout() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateOptions() {
|
||||
System.out.println("entering RecursiveAppender.activateOptions");
|
||||
if(activationDelay > 0) {
|
||||
Logger logger = LoggerFactory.getLogger(loggerName);
|
||||
logger.info("About to wait {} millis", activationDelay);
|
||||
try {
|
||||
Thread.sleep(activationDelay);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
logger.info("Done waiting {} millis", activationDelay);
|
||||
}
|
||||
super.activateOptions();
|
||||
|
||||
System.out.println("exiting RecursiveAppender.activateOptions");
|
||||
}
|
||||
public int getActivationDelay() {
|
||||
return activationDelay;
|
||||
}
|
||||
|
||||
public void setActivationDelay(int activationDelay) {
|
||||
this.activationDelay = activationDelay;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
14
slf4j-log4j12/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java
Normal file → Executable file
14
slf4j-log4j12/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java
Normal file → Executable file
|
|
@ -27,21 +27,17 @@ package org.slf4j.impl;
|
|||
import java.util.Random;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RecursiveInitializationTest {
|
||||
|
||||
// value of LogManager.DEFAULT_CONFIGURATION_KEY;
|
||||
static String CONFIG_FILE_KEY = "log4j.configuration";
|
||||
|
||||
int diff = new Random().nextInt(10000);
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
System.setProperty(CONFIG_FILE_KEY, "recursiveInit.properties");
|
||||
}
|
||||
String loggerName = "org.slf4j.impl.RecursiveInitializationTest";
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
|
|
@ -49,9 +45,9 @@ public class RecursiveInitializationTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testLog4j() {
|
||||
Logger logger = LoggerFactory.getLogger("x" + diff);
|
||||
System.out.println("logger class=" + logger.getClass().getName());
|
||||
public void loggingDuringInitialization() {
|
||||
System.setProperty(CONFIG_FILE_KEY, "recursiveInit.properties");
|
||||
Logger logger = LoggerFactory.getLogger(loggerName+".loggingDuringInitialization-"+diff);
|
||||
logger.info("hello");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
log4j.debug=true
|
||||
log4j.rootLogger=DEBUG, CONSOLE, RECURSIVE
|
||||
|
||||
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.CONSOLE.layout.ConversionPattern=CON %d [%t] %c - %m%n
|
||||
|
||||
log4j.appender.RECURSIVE=org.slf4j.impl.RecursiveAppender
|
||||
log4j.appender.RECURSIVE.activationDelay=10
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package org.slf4j;
|
||||
|
||||
public class LoggerFactoryFriend {
|
||||
static public void reset() {
|
||||
LoggerFactory.reset();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/**
|
||||
* Copyright (c) 2004-2016 QOS.ch
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package org.slf4j.impl;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.LoggerFactoryFriend;
|
||||
|
||||
public class MultithreadedInitializationTest {
|
||||
|
||||
final static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
|
||||
|
||||
private static AtomicLong EVENT_COUNT = new AtomicLong(0);
|
||||
|
||||
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
|
||||
int diff = new Random().nextInt(10000);
|
||||
String loggerName = "org.slf4j.impl.MultithreadedInitializationTest";
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
LoggerFactoryFriend.reset();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
LoggerFactoryFriend.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException {
|
||||
System.out.println("THREAD_COUNT=" + THREAD_COUNT);
|
||||
LoggerAccessingThread[] accessors = harness();
|
||||
|
||||
for (LoggerAccessingThread accessor : accessors) {
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
accessor.logger.info("post harness");
|
||||
}
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(loggerName + ".slowInitialization-" + diff);
|
||||
logger.info("hello");
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
|
||||
int NUM_LINES_IN_SLF4J_REPLAY_WARNING=3;
|
||||
//assertEquals(EVENT_COUNT.get()+NUM_LINES_IN_SLF4J_REPLAY_WARNING, sps.stringList.size());
|
||||
}
|
||||
|
||||
private static LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
|
||||
LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT];
|
||||
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i] = new LoggerAccessingThread(barrier, i);
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
barrier.await();
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
return threads;
|
||||
}
|
||||
|
||||
static class LoggerAccessingThread extends Thread {
|
||||
final CyclicBarrier barrier;
|
||||
Logger logger;
|
||||
int count;
|
||||
|
||||
LoggerAccessingThread(CyclicBarrier barrier, int count) {
|
||||
this.barrier = barrier;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
barrier.await();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
logger = LoggerFactory.getLogger(this.getClass().getName() + "-" + count);
|
||||
logger.info("in run method");
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +36,7 @@ import java.util.Date;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.event.LoggingEvent;
|
||||
import org.slf4j.helpers.FormattingTuple;
|
||||
import org.slf4j.helpers.MarkerIgnoringBase;
|
||||
import org.slf4j.helpers.MessageFormatter;
|
||||
|
|
@ -645,4 +646,14 @@ public class SimpleLogger extends MarkerIgnoringBase {
|
|||
public void error(String msg, Throwable t) {
|
||||
log(LOG_LEVEL_ERROR, msg, t);
|
||||
}
|
||||
|
||||
public void log(LoggingEvent event) {
|
||||
int levelInt = event.getLevel().toInt();
|
||||
|
||||
if (!isLevelEnabled(levelInt)) {
|
||||
return;
|
||||
}
|
||||
FormattingTuple tp = MessageFormatter.arrayFormat(event.getMessage(), event.getArgumentArray(), event.getThrowable());
|
||||
log(levelInt, tp.getMessage(), event.getThrowable());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package org.slf4j;
|
||||
|
||||
public class LoggerFactoryFriend {
|
||||
static public void reset() {
|
||||
LoggerFactory.reset();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/**
|
||||
* Copyright (c) 2004-2016 QOS.ch
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package org.slf4j.impl;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.LoggerFactoryFriend;
|
||||
|
||||
public class MultithreadedInitializationTest {
|
||||
|
||||
final static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
|
||||
|
||||
private static AtomicLong EVENT_COUNT = new AtomicLong(0);
|
||||
|
||||
private final PrintStream oldErr = System.err;
|
||||
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
|
||||
int diff = new Random().nextInt(10000);
|
||||
String loggerName = "org.slf4j.impl.MultithreadedInitializationTest";
|
||||
StringPrintStream sps = new StringPrintStream(oldErr);
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
LoggerFactoryFriend.reset();
|
||||
System.setErr(sps);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
LoggerFactoryFriend.reset();
|
||||
System.setErr(oldErr);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException {
|
||||
System.out.println("THREAD_COUNT=" + THREAD_COUNT);
|
||||
LoggerAccessingThread[] accessors = harness();
|
||||
|
||||
for (LoggerAccessingThread accessor : accessors) {
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
accessor.logger.info("post harness");
|
||||
}
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(loggerName + ".slowInitialization-" + diff);
|
||||
logger.info("hello");
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
|
||||
int NUM_LINES_IN_SLF4J_REPLAY_WARNING=3;
|
||||
assertEquals(EVENT_COUNT.get()+NUM_LINES_IN_SLF4J_REPLAY_WARNING, sps.stringList.size());
|
||||
}
|
||||
|
||||
private static LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
|
||||
LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT];
|
||||
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i] = new LoggerAccessingThread(barrier, i);
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
barrier.await();
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
return threads;
|
||||
}
|
||||
|
||||
static class LoggerAccessingThread extends Thread {
|
||||
final CyclicBarrier barrier;
|
||||
Logger logger;
|
||||
int count;
|
||||
|
||||
LoggerAccessingThread(CyclicBarrier barrier, int count) {
|
||||
this.barrier = barrier;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
barrier.await();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
logger = LoggerFactory.getLogger(this.getClass().getName() + "-" + count);
|
||||
logger.info("in run method");
|
||||
EVENT_COUNT.getAndIncrement();
|
||||
}
|
||||
};
|
||||
|
||||
public static class StringPrintStream extends PrintStream {
|
||||
|
||||
public static final String LINE_SEP = System.getProperty("line.separator");
|
||||
PrintStream other;
|
||||
List<String> stringList = new ArrayList<String>();
|
||||
|
||||
public StringPrintStream(PrintStream ps) {
|
||||
super(ps);
|
||||
other = ps;
|
||||
}
|
||||
|
||||
public void print(String s) {
|
||||
other.print(s);
|
||||
stringList.add(s);
|
||||
}
|
||||
|
||||
public void println(String s) {
|
||||
other.println(s);
|
||||
stringList.add(s);
|
||||
}
|
||||
|
||||
public void println(Object o) {
|
||||
other.println(o);
|
||||
stringList.add(o.toString());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -441,9 +441,9 @@ class B extends A {
|
|||
</p>
|
||||
|
||||
<p>However, as reported in <a
|
||||
href="http://bugzilla.slf4j.org/show_bug.cgi?id=68">bug 68</a>, in
|
||||
some environments it may be difficult to upgrade the log4j
|
||||
version. To accommodate such circumstances, SLF4J's
|
||||
href="http://jira.qos.ch/browse/SLF4J-59">issue 59</a>, in some
|
||||
environments it may be difficult to upgrade the log4j version. To
|
||||
accommodate such circumstances, SLF4J's
|
||||
<code>Log4jLoggerAdapter</code> will map the TRACE level as
|
||||
DEBUG.</p>
|
||||
|
||||
|
|
@ -452,13 +452,13 @@ class B extends A {
|
|||
were created during the default configuration phase of the
|
||||
underlying logging system</h3>
|
||||
|
||||
<p>Highly configurable logging systems such as logback and log4j
|
||||
may create components which invoke loggers during their own
|
||||
initialization. See issue <a
|
||||
href="http://jira.qos.ch/browse/LOGBACK-127">LOGBACK-127</a> for a
|
||||
typical occurrence. However, since the binding process with SLF4J
|
||||
has not yet completed (because the underlying logging system was
|
||||
not yet completely loaded into memory), it is not possible to
|
||||
<p> Highly configurable
|
||||
logging systems such as logback and log4j may create components
|
||||
which invoke loggers during their own initialization. See issue
|
||||
<a href="http://jira.qos.ch/browse/LOGBACK-127">LOGBACK-127</a>
|
||||
for a typical occurrence. However, since the binding process with
|
||||
SLF4J has not yet completed (because the underlying logging system
|
||||
was not yet completely loaded into memory), it is not possible to
|
||||
honor such logger creation requests.</p>
|
||||
|
||||
<p>To avoid this chicken-and-egg problem, SLF4J creates substitute
|
||||
|
|
@ -476,6 +476,23 @@ class B extends A {
|
|||
have been dropped.
|
||||
</p>
|
||||
|
||||
<h3 class="doAnchor" name="reply">A number (N) of logging calls
|
||||
during the initialization phase have been intercepted and are now
|
||||
being replayed. These are suject to the filtering rules of the
|
||||
underlying logging system.
|
||||
</h3>
|
||||
|
||||
<p><span class="label">since 1.7.15</span> As of SLF4J version
|
||||
1.7.15, logging calls made during the initilization phase are
|
||||
recorded and replayed post-inititilization.</p>
|
||||
|
||||
<p>These replayed logging calls are subject to filtering by the
|
||||
underlying logging system.</p>
|
||||
|
||||
<p>Replaying only occurs for apllications which are already
|
||||
multi-threaded when the first logging call occurs.
|
||||
</p>
|
||||
|
||||
|
||||
<script src="templates/footer.js" type="text/javascript"></script>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue