You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2013/04/01 05:51:23 UTC
svn commit: r1463078 [1/4] - in /logging/log4j/log4j2/trunk: ./
core/src/main/java/org/apache/logging/log4j/core/
core/src/main/java/org/apache/logging/log4j/core/appender/
core/src/main/java/org/apache/logging/log4j/core/config/
core/src/main/java/org...
Author: rgoers
Date: Mon Apr 1 03:51:21 2013
New Revision: 1463078
URL: http://svn.apache.org/r1463078
Log:
LOG4J2-163, LOG4J2-164, LOG4J2-151. LOG4J2-153. LOG4J2-157 - Add Asynchronous Loggers
Added:
logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/AsynchAppenderNoLocationTest.java
logging/log4j/log4j2/trunk/core/src/test/resources/log4j-asynch-no-location.xml
logging/log4j/log4j2/trunk/log4j-async/
logging/log4j/log4j2/trunk/log4j-async/pom.xml
logging/log4j/log4j2/trunk/log4j-async/src/
logging/log4j/log4j2/trunk/log4j-async/src/main/
logging/log4j/log4j2/trunk/log4j-async/src/main/java/
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLogger.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLoggerContext.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLoggerContextSelector.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/CachedClock.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/Clock.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/ClockFactory.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/CoarseCachedClock.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/RingBufferLogEvent.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/RingBufferLogEventHandler.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/RingBufferLogEventTranslator.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/SystemClock.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/appender/
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/appender/FastFileAppender.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/appender/FastFileManager.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/appender/FastRollingFileAppender.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/appender/FastRollingFileManager.java
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/config/
logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/config/AsyncLoggerConfig.java
logging/log4j/log4j2/trunk/log4j-async/src/site/
logging/log4j/log4j2/trunk/log4j-async/src/site/site.xml
logging/log4j/log4j2/trunk/log4j-async/src/site/xdoc/
logging/log4j/log4j2/trunk/log4j-async/src/site/xdoc/index.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/
logging/log4j/log4j2/trunk/log4j-async/src/test/java/
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/AsyncLoggerContextSelectorTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/AsyncLoggerContextTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/AsyncLoggerLocationTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/AsyncLoggerTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/CachedClockTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/ClockFactoryTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/SystemClockTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/appender/
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/appender/FastFileAppenderLocationTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/appender/FastFileAppenderTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/appender/FastRollingFileAppenderLocationTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/appender/FastRollingFileAppenderTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/config/
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/config/AsyncLoggerConfigTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/perftest/
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/perftest/IPerfTestRunner.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/perftest/MTPerfTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/perftest/PerfTest.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/perftest/PerfTestDriver.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/perftest/PerfTestResultFormatter.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/perftest/RunLog4j1.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/perftest/RunLog4j2.java
logging/log4j/log4j2/trunk/log4j-async/src/test/java/org/apache/logging/log4j/async/perftest/RunLogback.java
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/AsyncLoggerConfigTest.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/AsyncLoggerLocationTest.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/AsyncLoggerTest.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/FastFileAppenderLocationTest.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/FastFileAppenderTest.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/FastRollingFileAppenderLocationTest.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/FastRollingFileAppenderTest.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/log4j.dtd
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf-log4j12-async.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf-log4j12.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf-logback-async.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf-logback.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf1syncFastFile.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf1syncFile.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf2syncRollFastFile.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf2syncRollFile.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf3PlainNoLoc.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf4PlainLocation.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf5AsyncApndNoLoc.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf6AsyncApndLoc.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf7MixedNoLoc.xml
logging/log4j/log4j2/trunk/log4j-async/src/test/resources/perf8MixedLoc.xml
logging/log4j/log4j2/trunk/src/site/xdoc/manual/async.xml
Modified:
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Logger.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/AsynchAppender.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/lookup/DateLookupTest.java
logging/log4j/log4j2/trunk/core/src/test/resources/log4j-asynch.xml
logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEvent.java
logging/log4j/log4j2/trunk/pom.xml
logging/log4j/log4j2/trunk/src/changes/changes.xml
logging/log4j/log4j2/trunk/src/site/site.xml
logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LogEvent.java?rev=1463078&r1=1463077&r2=1463078&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LogEvent.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LogEvent.java Mon Apr 1 03:51:21 2013
@@ -104,4 +104,47 @@ public interface LogEvent extends Serial
*/
String getFQCN();
+ /**
+ * Returns whether the source of the logging request is required downstream.
+ * Asynchronous Loggers and Appenders use this flag to determine whether
+ * to take a {@code StackTrace} snapshot or not before handing off this
+ * event to another thread.
+ * @return {@code true} if the source of the logging request is required
+ * downstream, {@code false} otherwise.
+ * @see #getSource()
+ */
+ // see also LOG4J2-153
+ boolean isIncludeLocation();
+
+ /**
+ * Sets whether the source of the logging request is required downstream.
+ * Asynchronous Loggers and Appenders use this flag to determine whether
+ * to take a {@code StackTrace} snapshot or not before handing off this
+ * event to another thread.
+ * @param locationRequired {@code true} if the source of the logging request
+ * is required downstream, {@code false} otherwise.
+ * @see #getSource()
+ */
+ void setIncludeLocation(boolean locationRequired);
+
+ /**
+ * Returns {@code true} if this event is the last one in a batch,
+ * {@code false} otherwise. Used by asynchronous Loggers and Appenders to
+ * signal to buffered downstream components when to flush to disk, as a
+ * more efficient alternative to the {@code immediateFlush=true}
+ * configuration.
+ * @return whether this event is the last one in a batch.
+ */
+ // see also LOG4J2-164
+ boolean isEndOfBatch();
+
+ /**
+ * Sets whether this event is the last one in a batch.
+ * Used by asynchronous Loggers and Appenders to signal to buffered
+ * downstream components when to flush to disk, as a more efficient
+ * alternative to the {@code immediateFlush=true} configuration.
+ * @param endOfBatch {@code true} if this event is the last one in a batch,
+ * {@code false} otherwise.
+ */
+ void setEndOfBatch(boolean endOfBatch);
}
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Logger.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Logger.java?rev=1463078&r1=1463077&r2=1463078&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Logger.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Logger.java Mon Apr 1 03:51:21 2013
@@ -234,8 +234,9 @@ public class Logger extends AbstractLogg
* The binding between a Logger and its configuration.
*/
protected class PrivateConfig {
- private final LoggerConfig loggerConfig;
- private final Configuration config;
+ // config fields are public to make them visible to Logger subclasses
+ public final LoggerConfig loggerConfig;
+ public final Configuration config;
private final Level level;
private final int intLevel;
private final Logger logger;
@@ -264,7 +265,8 @@ public class Logger extends AbstractLogg
this.logger = pc.logger;
}
- protected void logEvent(final LogEvent event) {
+ // LOG4J2-151: changed visibility to public
+ public void logEvent(LogEvent event) {
config.getConfigurationMonitor().checkConfiguration();
loggerConfig.log(event);
}
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java?rev=1463078&r1=1463077&r2=1463078&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java Mon Apr 1 03:51:21 2013
@@ -326,8 +326,8 @@ public class LoggerContext implements or
}
}
-
- private Logger newInstance(final LoggerContext ctx, final String name, final MessageFactory messageFactory) {
+ // LOG4J2-151: changed visibility from private to protected
+ protected Logger newInstance(final LoggerContext ctx, final String name, final MessageFactory messageFactory) {
return new Logger(ctx, name, messageFactory);
}
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/AsynchAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/AsynchAppender.java?rev=1463078&r1=1463077&r2=1463078&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/AsynchAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/AsynchAppender.java Mon Apr 1 03:51:21 2013
@@ -56,18 +56,21 @@ public final class AsynchAppender<T exte
private final Configuration config;
private final AppenderRef[] appenderRefs;
private final String errorRef;
+ private final boolean includeLocation;
private AppenderControl errorAppender;
private AsynchThread thread;
private AsynchAppender(final String name, final Filter filter, final AppenderRef[] appenderRefs,
final String errorRef, final int queueSize, final boolean blocking,
- final boolean handleExceptions, final Configuration config) {
+ final boolean handleExceptions, final Configuration config,
+ final boolean includeLocation) {
super(name, filter, null, handleExceptions);
this.queue = new ArrayBlockingQueue<Serializable>(queueSize);
this.blocking = blocking;
this.config = config;
this.appenderRefs = appenderRefs;
this.errorRef = errorRef;
+ this.includeLocation = includeLocation;
}
@Override
@@ -123,13 +126,14 @@ public final class AsynchAppender<T exte
boolean appendSuccessful = false;
if (blocking){
try {
- queue.put(Log4jLogEvent.serialize((Log4jLogEvent) event)); // wait for free slots in the queue
+ // wait for free slots in the queue
+ queue.put(Log4jLogEvent.serialize((Log4jLogEvent) event, includeLocation));
appendSuccessful = true;
} catch (InterruptedException e) {
LOGGER.warn("Interrupted while waiting for a free slots in the LogEvent-queue at the AsynchAppender {}", getName());
}
} else {
- appendSuccessful = queue.offer(Log4jLogEvent.serialize((Log4jLogEvent) event));
+ appendSuccessful = queue.offer(Log4jLogEvent.serialize((Log4jLogEvent) event, includeLocation));
if (!appendSuccessful) {
error("Appender " + getName() + " is unable to write primary appenders. queue is full");
}
@@ -147,6 +151,7 @@ public final class AsynchAppender<T exte
* @param blocking True if the Appender should wait when the queue is full. The default is true.
* @param size The size of the event queue. The default is 128.
* @param name The name of the Appender.
+ * @param includeLocation whether to include location information. The default is false.
* @param filter The Filter or null.
* @param config The Configuration.
* @param suppress "true" if exceptions should be hidden from the application, "false" otherwise.
@@ -156,14 +161,15 @@ public final class AsynchAppender<T exte
*/
@PluginFactory
public static <S extends Serializable> AsynchAppender<S> createAppender(
- @PluginElement("appender-ref") final AppenderRef[] appenderRefs,
- @PluginAttr("error-ref") final String errorRef,
- @PluginAttr("blocking") final String blocking,
- @PluginAttr("bufferSize") final String size,
- @PluginAttr("name") final String name,
- @PluginElement("filter") final Filter filter,
- @PluginConfiguration final Configuration config,
- @PluginAttr("suppressExceptions") final String suppress) {
+ @PluginElement("appender-ref") final AppenderRef[] appenderRefs,
+ @PluginAttr("error-ref") final String errorRef,
+ @PluginAttr("blocking") final String blocking,
+ @PluginAttr("bufferSize") final String size,
+ @PluginAttr("name") final String name,
+ @PluginAttr("includeLocation") final String includeLocation,
+ @PluginElement("filter") final Filter filter,
+ @PluginConfiguration final Configuration config,
+ @PluginAttr("suppressExceptions") final String suppress) {
if (name == null) {
LOGGER.error("No name provided for AsynchAppender");
return null;
@@ -174,11 +180,13 @@ public final class AsynchAppender<T exte
final boolean isBlocking = blocking == null ? true : Boolean.valueOf(blocking);
final int queueSize = size == null ? DEFAULT_QUEUE_SIZE : Integer.parseInt(size);
+ final boolean isIncludeLocation = includeLocation == null ? false :
+ Boolean.parseBoolean(includeLocation);
final boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
- return new AsynchAppender<S>(name, filter, appenderRefs, errorRef, queueSize, isBlocking, handleExceptions,
- config);
+ return new AsynchAppender<S>(name, filter, appenderRefs, errorRef,
+ queueSize, isBlocking, handleExceptions, config, isIncludeLocation);
}
/**
@@ -210,8 +218,9 @@ public final class AsynchAppender<T exte
continue;
}
final Log4jLogEvent event = Log4jLogEvent.deserialize(s);
+ event.setEndOfBatch(queue.isEmpty());
boolean success = false;
- for (final AppenderControl control : appenders) {
+ for (final AppenderControl<?> control : appenders) {
try {
control.callAppender(event);
success = true;
@@ -233,7 +242,8 @@ public final class AsynchAppender<T exte
Serializable s = queue.take();
if (s instanceof Log4jLogEvent) {
final Log4jLogEvent event = Log4jLogEvent.deserialize(s);
- for (final AppenderControl control : appenders) {
+ event.setEndOfBatch(queue.isEmpty());
+ for (final AppenderControl<?> control : appenders) {
control.callAppender(event);
}
}
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java?rev=1463078&r1=1463077&r2=1463078&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java Mon Apr 1 03:51:21 2013
@@ -25,9 +25,11 @@ import org.apache.logging.log4j.core.Fil
import org.apache.logging.log4j.core.LifeCycle;
import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
import org.apache.logging.log4j.core.filter.AbstractFilterable;
+import org.apache.logging.log4j.core.helpers.Constants;
import org.apache.logging.log4j.core.impl.Log4jLogEvent;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.impl.LogEventFactory;
+import org.apache.logging.log4j.core.lookup.StrSubstitutor;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttr;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
@@ -38,6 +40,7 @@ import org.apache.logging.log4j.message.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -61,13 +64,13 @@ public class LoggerConfig extends Abstra
private LogEventFactory logEventFactory;
private Level level;
private boolean additive = true;
+ private boolean includeLocation = true;
private LoggerConfig parent;
private final AtomicInteger counter = new AtomicInteger();
private boolean shutdown = false;
private final Map<Property, Boolean> properties;
private final Configuration config;
-
/**
* Default constructor.
*/
@@ -81,11 +84,13 @@ public class LoggerConfig extends Abstra
/**
* Constructor that sets the name, level and additive values.
+ *
* @param name The Logger name.
* @param level The Level.
* @param additive true if the Logger is additive, false otherwise.
*/
- public LoggerConfig(final String name, final Level level, final boolean additive) {
+ public LoggerConfig(final String name, final Level level,
+ final boolean additive) {
this.logEventFactory = this;
this.name = name;
this.level = level;
@@ -94,14 +99,18 @@ public class LoggerConfig extends Abstra
this.config = null;
}
- protected LoggerConfig(final String name, final List<AppenderRef> appenders, final Filter filter, final Level level,
- final boolean additive, final Property[] properties, final Configuration config) {
+ protected LoggerConfig(final String name,
+ final List<AppenderRef> appenders, final Filter filter,
+ final Level level, final boolean additive,
+ final Property[] properties, final Configuration config,
+ final boolean includeLocation) {
super(filter);
this.logEventFactory = this;
this.name = name;
this.appenderRefs = appenders;
this.level = level;
this.additive = additive;
+ this.includeLocation = includeLocation;
this.config = config;
if (properties != null && properties.length > 0) {
this.properties = new HashMap<Property, Boolean>(properties.length);
@@ -121,6 +130,7 @@ public class LoggerConfig extends Abstra
/**
* Returns the name of the LoggerConfig.
+ *
* @return the name of the LoggerConfig.
*/
public String getName() {
@@ -129,6 +139,7 @@ public class LoggerConfig extends Abstra
/**
* Sets the parent of this LoggerConfig.
+ *
* @param parent the parent LoggerConfig.
*/
public void setParent(final LoggerConfig parent) {
@@ -137,6 +148,7 @@ public class LoggerConfig extends Abstra
/**
* Returns the parent of this LoggerConfig.
+ *
* @return the LoggerConfig that is the parent of this one.
*/
public LoggerConfig getParent() {
@@ -145,16 +157,20 @@ public class LoggerConfig extends Abstra
/**
* Adds an Appender to the LoggerConfig.
+ *
* @param appender The Appender to add.
* @param level The Level to use.
* @param filter A Filter for the Appender reference.
*/
- public void addAppender(final Appender appender, final Level level, final Filter filter) {
- appenders.put(appender.getName(), new AppenderControl(appender, level, filter));
+ public void addAppender(final Appender appender, final Level level,
+ final Filter filter) {
+ appenders.put(appender.getName(), new AppenderControl(appender, level,
+ filter));
}
/**
* Removes the Appender with the specific name.
+ *
* @param name The name of the Appender.
*/
public void removeAppender(final String name) {
@@ -166,11 +182,14 @@ public class LoggerConfig extends Abstra
/**
* Returns all Appenders as a Map.
- * @return a Map with the Appender name as the key and the Appender as the value.
+ *
+ * @return a Map with the Appender name as the key and the Appender as the
+ * value.
*/
public Map<String, Appender<?>> getAppenders() {
final Map<String, Appender<?>> map = new HashMap<String, Appender<?>>();
- for (final Map.Entry<String, AppenderControl<?>> entry : appenders.entrySet()) {
+ for (final Map.Entry<String, AppenderControl<?>> entry : appenders
+ .entrySet()) {
map.put(entry.getKey(), entry.getValue().getAppender());
}
return map;
@@ -202,6 +221,7 @@ public class LoggerConfig extends Abstra
/**
* Returns the Appender references.
+ *
* @return a List of all the Appender names attached to this LoggerConfig.
*/
public List<AppenderRef> getAppenderRefs() {
@@ -210,6 +230,7 @@ public class LoggerConfig extends Abstra
/**
* Sets the logging Level.
+ *
* @param level The logging Level.
*/
public void setLevel(final Level level) {
@@ -218,6 +239,7 @@ public class LoggerConfig extends Abstra
/**
* Returns the logging Level.
+ *
* @return the logging Level.
*/
public Level getLevel() {
@@ -226,6 +248,7 @@ public class LoggerConfig extends Abstra
/**
* Returns the LogEventFactory.
+ *
* @return the LogEventFactory.
*/
public LogEventFactory getLogEventFactory() {
@@ -233,7 +256,9 @@ public class LoggerConfig extends Abstra
}
/**
- * Sets the LogEventFactory. Usually the LogEventFactory will be this LoggerConfig.
+ * Sets the LogEventFactory. Usually the LogEventFactory will be this
+ * LoggerConfig.
+ *
* @param logEventFactory the LogEventFactory.
*/
public void setLogEventFactory(final LogEventFactory logEventFactory) {
@@ -242,6 +267,7 @@ public class LoggerConfig extends Abstra
/**
* Returns the valid of the additive flag.
+ *
* @return true if the LoggerConfig is additive, false otherwise.
*/
public boolean isAdditive() {
@@ -250,14 +276,47 @@ public class LoggerConfig extends Abstra
/**
* Sets the additive setting.
- * @param additive true if thee LoggerConfig should be additive, false otherwise.
+ *
+ * @param additive true if the LoggerConfig should be additive, false
+ * otherwise.
*/
public void setAdditive(final boolean additive) {
this.additive = additive;
}
/**
+ * Returns the value of logger configuration attribute {@code includeLocation},
+ * or, if no such attribute was configured, {@code true} if logging is
+ * synchronous or {@code false} if logging is asynchronous.
+ *
+ * @return whether location should be passed downstream
+ */
+ public boolean isIncludeLocation() {
+ return includeLocation;
+ }
+
+ /**
+ * Returns an unmodifiable map with the configuration properties, or
+ * {@code null} if this {@code LoggerConfig} does not have any configuration
+ * properties.
+ * <p>
+ * For each {@code Property} key in the map, the value is {@code true} if
+ * the property value has a variable that needs to be substituted.
+ *
+ * @return an unmodifiable map with the configuration properties, or
+ * {@code null}
+ * @see Configuration#getSubst()
+ * @see StrSubstitutor
+ */
+ // LOG4J2-157
+ public Map<Property, Boolean> getProperties() {
+ return properties == null ? null : Collections
+ .unmodifiableMap(properties);
+ }
+
+ /**
* Logs an event.
+ *
* @param loggerName The name of the Logger.
* @param marker A Marker or null if none is present.
* @param fqcn The fully qualified class name of the caller.
@@ -265,24 +324,29 @@ public class LoggerConfig extends Abstra
* @param data The Message.
* @param t A Throwable or null.
*/
- public void log(final String loggerName, final Marker marker, final String fqcn, final Level level,
- final Message data, final Throwable t) {
+ public void log(final String loggerName, final Marker marker,
+ final String fqcn, final Level level, final Message data,
+ final Throwable t) {
List<Property> props = null;
if (properties != null) {
props = new ArrayList<Property>(properties.size());
- for (final Map.Entry<Property, Boolean> entry : properties.entrySet()) {
+ for (final Map.Entry<Property, Boolean> entry : properties
+ .entrySet()) {
final Property prop = entry.getKey();
- final String value = entry.getValue() ? config.getSubst().replace(prop.getValue()) : prop.getValue();
+ final String value = entry.getValue() ? config.getSubst()
+ .replace(prop.getValue()) : prop.getValue();
props.add(Property.createProperty(prop.getName(), value));
}
}
- final LogEvent event = logEventFactory.createEvent(loggerName, marker, fqcn, level, data, props, t);
+ final LogEvent event = logEventFactory.createEvent(loggerName, marker,
+ fqcn, level, data, props, t);
log(event);
}
/**
- * Waits for all log events to complete before shutting down this loggerConfig.
+ * Waits for all log events to complete before shutting down this
+ * loggerConfig.
*/
private synchronized void waitForCompletion() {
if (shutdown) {
@@ -303,6 +367,7 @@ public class LoggerConfig extends Abstra
/**
* Logs an event.
+ *
* @param event The log event.
*/
public void log(final LogEvent event) {
@@ -313,6 +378,8 @@ public class LoggerConfig extends Abstra
return;
}
+ event.setIncludeLocation(isIncludeLocation());
+
callAppenders(event);
if (additive && parent != null) {
@@ -330,7 +397,7 @@ public class LoggerConfig extends Abstra
}
}
- private void callAppenders(final LogEvent event) {
+ protected void callAppenders(final LogEvent event) {
for (final AppenderControl control : appenders.values()) {
control.callAppender(event);
}
@@ -338,6 +405,7 @@ public class LoggerConfig extends Abstra
/**
* Creates a log event.
+ *
* @param loggerName The name of the Logger.
* @param marker An optional Marker.
* @param fqcn The fully qualified class name of the caller.
@@ -347,9 +415,11 @@ public class LoggerConfig extends Abstra
* @param t An optional Throwable.
* @return The LogEvent.
*/
- public LogEvent createEvent(final String loggerName, final Marker marker, final String fqcn, final Level level,
- final Message data, final List<Property> properties, final Throwable t) {
- return new Log4jLogEvent(loggerName, marker, fqcn, level, data, properties, t);
+ public LogEvent createEvent(final String loggerName, final Marker marker,
+ final String fqcn, final Level level, final Message data,
+ final List<Property> properties, final Throwable t) {
+ return new Log4jLogEvent(loggerName, marker, fqcn, level, data,
+ properties, t);
}
@Override
@@ -359,9 +429,11 @@ public class LoggerConfig extends Abstra
/**
* Factory method to create a LoggerConfig.
+ *
* @param additivity True if additive, false otherwise.
* @param levelName The Level to be associated with the Logger.
* @param loggerName The name of the Logger.
+ * @param includeLocation whether location should be passed downstream
* @param refs An array of Appender names.
* @param properties Properties to pass to the Logger.
* @param config The Configuration.
@@ -369,13 +441,15 @@ public class LoggerConfig extends Abstra
* @return A new LoggerConfig.
*/
@PluginFactory
- public static LoggerConfig createLogger(@PluginAttr("additivity") final String additivity,
- @PluginAttr("level") final String levelName,
- @PluginAttr("name") final String loggerName,
- @PluginElement("appender-ref") final AppenderRef[] refs,
- @PluginElement("properties") final Property[] properties,
- @PluginConfiguration final Configuration config,
- @PluginElement("filters") final Filter filter) {
+ public static LoggerConfig createLogger(
+ @PluginAttr("additivity") final String additivity,
+ @PluginAttr("level") final String levelName,
+ @PluginAttr("name") final String loggerName,
+ @PluginAttr("includeLocation") final String includeLocation,
+ @PluginElement("appender-ref") final AppenderRef[] refs,
+ @PluginElement("properties") final Property[] properties,
+ @PluginConfiguration final Configuration config,
+ @PluginElement("filters") final Filter filter) {
if (loggerName == null) {
LOGGER.error("Loggers cannot be configured without a name");
return null;
@@ -386,13 +460,28 @@ public class LoggerConfig extends Abstra
try {
level = Level.toLevel(levelName, Level.ERROR);
} catch (final Exception ex) {
- LOGGER.error("Invalid Log level specified: {}. Defaulting to Error", levelName);
+ LOGGER.error(
+ "Invalid Log level specified: {}. Defaulting to Error",
+ levelName);
level = Level.ERROR;
}
final String name = loggerName.equals("root") ? "" : loggerName;
- final boolean additive = additivity == null ? true : Boolean.parseBoolean(additivity);
+ final boolean additive = additivity == null ? true : Boolean
+ .parseBoolean(additivity);
- return new LoggerConfig(name, appenderRefs, filter, level, additive, properties, config);
+ return new LoggerConfig(name, appenderRefs, filter, level, additive,
+ properties, config, includeLocation(includeLocation));
+ }
+
+ // Note: for asynchronous loggers, includeLocation default is FALSE,
+ // for synchronous loggers, includeLocation default is TRUE.
+ private static boolean includeLocation(String includeLocationConfigValue) {
+ if (includeLocationConfigValue == null) {
+ final boolean sync = !"org.apache.logging.log4j.async.AsyncLoggerContextSelector"
+ .equals(System.getProperty(Constants.LOG4J_CONTEXT_SELECTOR));
+ return sync;
+ }
+ return Boolean.parseBoolean(includeLocationConfigValue);
}
/**
@@ -402,24 +491,30 @@ public class LoggerConfig extends Abstra
public static class RootLogger extends LoggerConfig {
@PluginFactory
- public static LoggerConfig createLogger(@PluginAttr("additivity") final String additivity,
- @PluginAttr("level") final String levelName,
- @PluginElement("appender-ref") final AppenderRef[] refs,
- @PluginElement("properties") final Property[] properties,
- @PluginConfiguration final Configuration config,
- @PluginElement("filters") final Filter filter) {
+ public static LoggerConfig createLogger(
+ @PluginAttr("additivity") final String additivity,
+ @PluginAttr("level") final String levelName,
+ @PluginAttr("includeLocation") final String includeLocation,
+ @PluginElement("appender-ref") final AppenderRef[] refs,
+ @PluginElement("properties") final Property[] properties,
+ @PluginConfiguration final Configuration config,
+ @PluginElement("filters") final Filter filter) {
final List<AppenderRef> appenderRefs = Arrays.asList(refs);
Level level;
try {
level = Level.toLevel(levelName, Level.ERROR);
} catch (final Exception ex) {
- LOGGER.error("Invalid Log level specified: {}. Defaulting to Error", levelName);
+ LOGGER.error(
+ "Invalid Log level specified: {}. Defaulting to Error",
+ levelName);
level = Level.ERROR;
}
- final boolean additive = additivity == null ? true : Boolean.parseBoolean(additivity);
+ final boolean additive = additivity == null ? true : Boolean
+ .parseBoolean(additivity);
- return new LoggerConfig(LogManager.ROOT_LOGGER_NAME, appenderRefs, filter, level, additive, properties,
- config);
+ return new LoggerConfig(LogManager.ROOT_LOGGER_NAME, appenderRefs,
+ filter, level, additive, properties, config,
+ includeLocation(includeLocation));
}
}
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java?rev=1463078&r1=1463077&r2=1463078&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java Mon Apr 1 03:51:21 2013
@@ -49,6 +49,8 @@ public class Log4jLogEvent implements Lo
private final ThreadContext.ContextStack ndc;
private String threadName = null;
private StackTraceElement location;
+ private boolean includeLocation;
+ private boolean endOfBatch = false;
/**
* Constructor.
@@ -222,31 +224,54 @@ public class Log4jLogEvent implements Lo
* @return the StackTraceElement for the caller.
*/
public StackTraceElement getSource() {
- if (fqcnOfLogger == null) {
+ if (location != null) {
+ return location;
+ }
+ if (fqcnOfLogger == null || !includeLocation) {
return null;
}
- if (location == null) {
- final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
- boolean next = false;
- for (final StackTraceElement element : stackTrace) {
- final String className = element.getClassName();
- if (next) {
- if (fqcnOfLogger.equals(className)) {
- continue;
- }
- location = element;
- break;
- }
+ location = calcLocation(fqcnOfLogger);
+ return location;
+ }
+ public static StackTraceElement calcLocation(String fqcnOfLogger) {
+ if (fqcnOfLogger == null) {
+ return null;
+ }
+ final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ boolean next = false;
+ for (final StackTraceElement element : stackTrace) {
+ final String className = element.getClassName();
+ if (next) {
if (fqcnOfLogger.equals(className)) {
- next = true;
- } else if (NOT_AVAIL.equals(className)) {
- break;
+ continue;
}
+ return element;
+ }
+
+ if (fqcnOfLogger.equals(className)) {
+ next = true;
+ } else if (NOT_AVAIL.equals(className)) {
+ break;
}
}
+ return null;
+ }
- return location;
+ public boolean isIncludeLocation() {
+ return includeLocation;
+ }
+
+ public void setIncludeLocation(boolean includeLocation) {
+ this.includeLocation = includeLocation;
+ }
+
+ public boolean isEndOfBatch() {
+ return endOfBatch;
+ }
+
+ public void setEndOfBatch(boolean endOfBatch) {
+ this.endOfBatch = endOfBatch;
}
/**
@@ -254,11 +279,12 @@ public class Log4jLogEvent implements Lo
* @return a LogEventProxy.
*/
protected Object writeReplace() {
- return new LogEventProxy(this);
+ return new LogEventProxy(this, this.includeLocation);
}
- public static Serializable serialize(final Log4jLogEvent event) {
- return new LogEventProxy(event);
+ public static Serializable serialize(final Log4jLogEvent event,
+ final boolean includeLocation) {
+ return new LogEventProxy(event, includeLocation);
}
public static Log4jLogEvent deserialize(final Serializable event) {
@@ -267,8 +293,13 @@ public class Log4jLogEvent implements Lo
}
if (event instanceof LogEventProxy) {
final LogEventProxy proxy = (LogEventProxy) event;
- return new Log4jLogEvent(proxy.name, proxy.marker, proxy.fqcnOfLogger, proxy.level, proxy.message,
- proxy.throwable, proxy.mdc, proxy.ndc, proxy.threadName, proxy.location, proxy.timestamp);
+ Log4jLogEvent result = new Log4jLogEvent(proxy.name, proxy.marker,
+ proxy.fqcnOfLogger, proxy.level, proxy.message,
+ proxy.throwable, proxy.mdc, proxy.ndc, proxy.threadName,
+ proxy.location, proxy.timestamp);
+ result.setEndOfBatch(proxy.isEndOfBatch);
+ result.setIncludeLocation(proxy.isLocationRequired);
+ return result;
}
throw new IllegalArgumentException("Event is not a serialized LogEvent: " + event.toString());
}
@@ -304,8 +335,10 @@ public class Log4jLogEvent implements Lo
private final ThreadContext.ContextStack ndc;
private final String threadName;
private final StackTraceElement location;
+ private final boolean isLocationRequired;
+ private final boolean isEndOfBatch;
- public LogEventProxy(final Log4jLogEvent event) {
+ public LogEventProxy(final Log4jLogEvent event, boolean includeLocation) {
this.fqcnOfLogger = event.fqcnOfLogger;
this.marker = event.marker;
this.level = event.level;
@@ -315,8 +348,10 @@ public class Log4jLogEvent implements Lo
this.throwable = event.throwable;
this.mdc = event.mdc;
this.ndc = event.ndc;
- this.location = event.getSource();
+ this.location = includeLocation ? event.getSource() : null;
this.threadName = event.getThreadName();
+ this.isLocationRequired = includeLocation;
+ this.isEndOfBatch = event.endOfBatch;
}
/**
@@ -324,10 +359,12 @@ public class Log4jLogEvent implements Lo
* @return Log4jLogEvent.
*/
protected Object readResolve() {
- return new Log4jLogEvent(name, marker, fqcnOfLogger, level, message, throwable, mdc, ndc, threadName,
- location, timestamp);
+ Log4jLogEvent result = new Log4jLogEvent(name, marker, fqcnOfLogger,
+ level, message, throwable, mdc, ndc, threadName, location,
+ timestamp);
+ result.setEndOfBatch(isEndOfBatch);
+ result.setIncludeLocation(isLocationRequired);
+ return result;
}
-
}
-
}
Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/AsynchAppenderNoLocationTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/AsynchAppenderNoLocationTest.java?rev=1463078&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/AsynchAppenderNoLocationTest.java (added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/AsynchAppenderNoLocationTest.java Mon Apr 1 03:51:21 2013
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class AsynchAppenderNoLocationTest {
+ private static final String CONFIG = "log4j-asynch-no-location.xml";
+ private static Configuration config;
+ private static ListAppender app;
+ private static LoggerContext ctx;
+
+ @BeforeClass
+ public static void setupClass() {
+ System.setProperty(XMLConfigurationFactory.CONFIGURATION_FILE_PROPERTY, CONFIG);
+ ctx = (LoggerContext) LogManager.getContext(false);
+ config = ctx.getConfiguration();
+ for (final Map.Entry<String, Appender<?>> entry : config.getAppenders().entrySet()) {
+ if (entry.getKey().equals("List")) {
+ app = (ListAppender) entry.getValue();
+ break;
+ }
+ }
+ }
+
+ @AfterClass
+ public static void cleanupClass() {
+ System.clearProperty(XMLConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
+ ctx.reconfigure();
+ StatusLogger.getLogger().reset();
+ }
+
+ @After
+ public void after() {
+ app.clear();
+ }
+
+ @Test
+ public void testNoLocation() throws Exception {
+ final Logger logger = LogManager.getLogger(AsynchAppender.class);
+ logger.error("This is a test");
+ logger.warn("Hello world!");
+ Thread.sleep(100);
+ final List<String> list = app.getMessages();
+ assertNotNull("No events generated", list);
+ assertTrue("Incorrect number of events. Expected 2, got " + list.size(), list.size() == 2);
+ String msg = list.get(0);
+ String expected = "? This is a test";
+ assertTrue("Expected " + expected + ", Actual " + msg, expected.equals(msg));
+ msg = list.get(1);
+ expected = "? Hello world!";
+ assertTrue("Expected " + expected + ", Actual " + msg, expected.equals(msg));
+ }
+}
Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/lookup/DateLookupTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/lookup/DateLookupTest.java?rev=1463078&r1=1463077&r2=1463078&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/lookup/DateLookupTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/lookup/DateLookupTest.java Mon Apr 1 03:51:21 2013
@@ -94,5 +94,19 @@ public class DateLookupTest {
public String getFQCN() {
return null;
}
+
+ public boolean isEndOfBatch() {
+ return false;
+ }
+
+ public void setEndOfBatch(boolean endOfBatch) {
+ }
+
+ public boolean isIncludeLocation() {
+ return false;
+ }
+
+ public void setIncludeLocation(boolean locationRequired) {
+ }
}
}
Added: logging/log4j/log4j2/trunk/core/src/test/resources/log4j-asynch-no-location.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j-asynch-no-location.xml?rev=1463078&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j-asynch-no-location.xml (added)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j-asynch-no-location.xml Mon Apr 1 03:51:21 2013
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<configuration status="error" name="RoutingTest" packages="org.apache.logging.log4j.test">
+
+ <appenders>
+ <Console name="STDOUT">
+ <PatternLayout pattern="%m%n"/>
+ </Console>
+ <List name="List">
+ <PatternLayout pattern="%C %M %m"/>
+ </List>
+ <Asynch name="Asynch"> <!-- includeLocation="false" the default for async -->
+ <appender-ref ref="List"/>
+ </Asynch>
+ </appenders>
+
+ <loggers>
+ <root level="debug">
+ <appender-ref ref="Asynch"/>
+ </root>
+ </loggers>
+
+</configuration>
\ No newline at end of file
Modified: logging/log4j/log4j2/trunk/core/src/test/resources/log4j-asynch.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j-asynch.xml?rev=1463078&r1=1463077&r2=1463078&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j-asynch.xml (original)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j-asynch.xml Mon Apr 1 03:51:21 2013
@@ -25,7 +25,7 @@
<List name="List">
<PatternLayout pattern="%C %M %m"/>
</List>
- <Asynch name="Asynch">
+ <Asynch name="Asynch" includeLocation="true">
<appender-ref ref="List"/>
</Asynch>
</appenders>
Modified: logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEvent.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEvent.java?rev=1463078&r1=1463077&r2=1463078&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEvent.java (original)
+++ logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEvent.java Mon Apr 1 03:51:21 2013
@@ -277,4 +277,24 @@ public class FlumeEvent extends SimpleEv
public ThreadContext.ContextStack getContextStack() {
return event.getContextStack();
}
+
+ @Override
+ public boolean isIncludeLocation() {
+ return event.isIncludeLocation();
+ }
+
+ @Override
+ public void setIncludeLocation(boolean includeLocation) {
+ event.setIncludeLocation(includeLocation);
+ }
+
+ @Override
+ public boolean isEndOfBatch() {
+ return event.isEndOfBatch();
+ }
+
+ @Override
+ public void setEndOfBatch(boolean endOfBatch) {
+ event.setEndOfBatch(endOfBatch);
+ }
}
Added: logging/log4j/log4j2/trunk/log4j-async/pom.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-async/pom.xml?rev=1463078&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-async/pom.xml (added)
+++ logging/log4j/log4j2/trunk/log4j-async/pom.xml Mon Apr 1 03:51:21 2013
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>log4j</artifactId>
+ <groupId>org.apache.logging.log4j</groupId>
+ <version>2.0-beta5-SNAPSHOT</version>
+ <relativePath>../</relativePath>
+ </parent>
+
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-async</artifactId>
+ <packaging>jar</packaging>
+ <name>Apache Log4j Async</name>
+ <description>Log4j 2.0 Asynchronous Loggers for Low Latency Logging</description>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <log4jParentDir>${basedir}/..</log4jParentDir>
+ <docLabel>Asynchronous Logging Documentation</docLabel>
+ <projectDir>/log4j-async</projectDir>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.lmax</groupId>
+ <artifactId>disruptor</artifactId>
+ <version>3.0.0.beta3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j.adapters</groupId>
+ <artifactId>log4j-1.2-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkMode>always</forkMode>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <executions>
+ <execution>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <mainClass>org.apache.logging.log4j.core.config.plugins.PluginManager</mainClass>
+ <arguments>
+ <argument>${project.build.outputDirectory}</argument>
+ <argument>org.apache.logging.log4j.async</argument>
+ </arguments>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-changes-plugin</artifactId>
+ <version>${changes.plugin.version}</version>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>changes-report</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ <configuration>
+ <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
+ <useJql>true</useJql>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>2.7</version>
+ <configuration>
+ <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
+ <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
+ <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
+ <enableRulesSummary>false</enableRulesSummary>
+ <propertyExpansion>basedir=${basedir}</propertyExpansion>
+ <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>${javadoc.plugin.version}</version>
+ <configuration>
+ <bottom>Copyright © {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved. Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, and the
+ Apache Logging project logo are trademarks of The Apache Software Foundation.</bottom>
+ <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating
+ project -->
+ <detectOfflineLinks>false</detectOfflineLinks>
+ <linksource>true</linksource>
+ <tags>
+ <tag>
+ <name>issue</name>
+ <placement>a</placement>
+ <head>JIRA issue:</head>
+ </tag>
+ <tag>
+ <name>doubt</name>
+ <placement>a</placement>
+ <head>Troublesome:</head>
+ </tag>
+ <tag>
+ <name>compare</name>
+ <placement>a</placement>
+ <head>Compare with:</head>
+ </tag>
+ </tags>
+ </configuration>
+ <reportSets>
+ <reportSet>
+ <id>non-aggregate</id>
+ <reports>
+ <report>javadoc</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <!--
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <threshold>Normal</threshold>
+ <effort>Default</effort>
+ <excludeFilterFile>findbugs-exclude-filter.xml</excludeFilterFile>
+ </configuration>
+ </plugin>
+ -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.3</version>
+ <reportSets>
+ <reportSet>
+ <id>non-aggregate</id>
+ <reports>
+ <report>jxr</report>
+ </reports>
+ </reportSet>
+ <reportSet>
+ <id>aggregate</id>
+ <reports>
+ <report>aggregate</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>${pmd.plugin.version}</version>
+ <configuration>
+ <targetJdk>1.5</targetJdk>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>2.2</version>
+ <reportSets>
+ <reportSet>
+ <!-- Disabled at it kills the site generation via a NoClassDefFoundError -->
+ <reports />
+ </reportSet>
+ </reportSets>
+ </plugin>
+ </plugins>
+ </reporting>
+
+</project>
\ No newline at end of file
Added: logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLogger.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLogger.java?rev=1463078&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLogger.java (added)
+++ logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLogger.java Mon Apr 1 03:51:21 2013
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.async;
+
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Property;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.MessageFactory;
+import org.apache.logging.log4j.status.StatusLogger;
+
+import com.lmax.disruptor.BlockingWaitStrategy;
+import com.lmax.disruptor.EventHandler;
+import com.lmax.disruptor.ExceptionHandler;
+import com.lmax.disruptor.RingBuffer;
+import com.lmax.disruptor.SleepingWaitStrategy;
+import com.lmax.disruptor.WaitStrategy;
+import com.lmax.disruptor.YieldingWaitStrategy;
+import com.lmax.disruptor.dsl.Disruptor;
+import com.lmax.disruptor.dsl.ProducerType;
+import com.lmax.disruptor.util.Util;
+
+/**
+ * AsyncLogger is a logger designed for high throughput and low latency logging.
+ * It does not perform any I/O in the calling (application) thread, but instead
+ * hands off the work to another thread as soon as possible. The actual logging
+ * is performed in the background thread. It uses the LMAX Disruptor library for
+ * inter-thread communication. (<a
+ * href="http://lmax-exchange.github.com/disruptor/"
+ * >http://lmax-exchange.github.com/disruptor/</a>)
+ * <p>
+ * To use AsyncLogger, specify the System property
+ * -DLog4jContextSelector=log4j.async.AsyncLoggerContextSelector before you
+ * obtain a Logger, and all Loggers returned by LogManager.getLogger will be
+ * AsyncLoggers.
+ * <p>
+ * Note that for performance reasons, this logger does not support source
+ * location. Any %class, %location or %line conversion patterns in your
+ * log4j.xml configuration will produce either a "?" character or no output at
+ * all.
+ * <p>
+ * For best performance, use AsyncLogger with the FastFileAppender or
+ * FastRollingFileAppender, with immediateFlush=false. These appenders have
+ * built-in support for the batching mechanism used by the Disruptor library,
+ * and they will flush to disk at the end of each batch. This means that even
+ * with immediateFlush=false, there will never be any items left in the buffer;
+ * all log events will all be written to disk in a very efficient manner.
+ */
+public class AsyncLogger extends Logger { // depends on LOG4J2-151
+ private static final StatusLogger LOGGER = StatusLogger.getLogger();
+ private static volatile Disruptor<RingBufferLogEvent> disruptor;
+ private static Clock clock = ClockFactory.getClock();
+
+ private static ExecutorService executor = Executors
+ .newSingleThreadExecutor();
+ private ThreadLocal<Info> threadlocalInfo = new ThreadLocal<Info>();
+
+ static {
+ int ringBufferSize = calculateRingBufferSize();
+
+ WaitStrategy waitStrategy = createWaitStrategy();
+ disruptor = new Disruptor<RingBufferLogEvent>(
+ RingBufferLogEvent.FACTORY, ringBufferSize, executor,
+ ProducerType.MULTI, waitStrategy);
+ EventHandler<RingBufferLogEvent>[] handlers = new RingBufferLogEventHandler[] { new RingBufferLogEventHandler() };
+ disruptor.handleExceptionsWith(getExceptionHandler());
+ disruptor.handleEventsWith(handlers);
+
+ LOGGER.debug(
+ "Starting AsyncLogger disruptor with ringbuffer size {}...",
+ disruptor.getRingBuffer().getBufferSize());
+ disruptor.start();
+ }
+
+ private static int calculateRingBufferSize() {
+ String userPreferredRBSize = System.getProperty(
+ "AsyncLogger.RingBufferSize", "256000");
+ int ringBufferSize = 256000; // default
+ try {
+ int size = Integer.parseInt(userPreferredRBSize);
+ if (size < 128) {
+ size = 128;
+ LOGGER.warn(
+ "Invalid RingBufferSize {}, using minimum size 128.",
+ userPreferredRBSize);
+ }
+ ringBufferSize = size;
+ } catch (Exception ex) {
+ LOGGER.warn("Invalid RingBufferSize {}, using default size.",
+ userPreferredRBSize);
+ }
+ return Util.ceilingNextPowerOfTwo(ringBufferSize);
+ }
+
+ private static WaitStrategy createWaitStrategy() {
+ String strategy = System.getProperty("AsyncLogger.WaitStrategy");
+ LOGGER.debug("property AsyncLogger.WaitStrategy={}", strategy);
+ if ("Sleep".equals(strategy)) {
+ LOGGER.debug("disruptor event handler uses SleepingWaitStrategy");
+ return new SleepingWaitStrategy();
+ } else if ("Yield".equals(strategy)) {
+ LOGGER.debug("disruptor event handler uses YieldingWaitStrategy");
+ return new YieldingWaitStrategy();
+ } else if ("Block".equals(strategy)) {
+ LOGGER.debug("disruptor event handler uses BlockingWaitStrategy");
+ return new BlockingWaitStrategy();
+ }
+ LOGGER.debug("disruptor event handler uses SleepingWaitStrategy");
+ return new SleepingWaitStrategy();
+ }
+
+ private static ExceptionHandler getExceptionHandler() {
+ String cls = System.getProperty("AsyncLogger.ExceptionHandler");
+ if (cls == null) {
+ LOGGER.debug("No AsyncLogger.ExceptionHandler specified");
+ return null;
+ }
+ try {
+ @SuppressWarnings("unchecked")
+ Class<? extends ExceptionHandler> klass = (Class<? extends ExceptionHandler>) Class
+ .forName(cls);
+ ExceptionHandler result = klass.newInstance();
+ LOGGER.debug("AsyncLogger.ExceptionHandler=" + result);
+ return result;
+ } catch (Exception ignored) {
+ LOGGER.debug(
+ "AsyncLogger.ExceptionHandler not set: error creating "
+ + cls + ": ", ignored);
+ return null;
+ }
+ }
+
+ private static class Info {
+ RingBufferLogEventTranslator translator;
+ String cachedThreadName;
+ }
+
+ public AsyncLogger(LoggerContext context, String name,
+ MessageFactory messageFactory) {
+ super(context, name, messageFactory);
+ }
+
+ @Override
+ public void log(Marker marker, String fqcn, Level level, Message data,
+ Throwable t) {
+ Info info = threadlocalInfo.get();
+ if (info == null) {
+ info = new Info();
+ info.translator = new RingBufferLogEventTranslator();
+ info.cachedThreadName = Thread.currentThread().getName();
+ threadlocalInfo.set(info);
+ }
+
+ Boolean includeLocation = config.loggerConfig.isIncludeLocation();
+ info.translator.setValues(this, getName(), marker, fqcn, level, data,
+ t, //
+
+ // config properties are taken care of in the EventHandler
+ // thread in the #actualAsyncLog method
+
+ // needs shallow copy to be fast (LOG4J2-154)
+ ThreadContext.getImmutableContext(),//
+
+ // needs shallow copy to be fast (LOG4J2-154)
+ ThreadContext.getImmutableStack(), //
+
+ // Thread.currentThread().getName(), //
+ info.cachedThreadName, //
+
+ // location: very expensive operation. LOG4J2-153:
+ // Only include if "includeLocation=true" is specified,
+ // exclude if not specified or if "false" was specified.
+ includeLocation != null && includeLocation ? location(fqcn)
+ : null,
+
+ // System.currentTimeMillis());
+ // CoarseCachedClock: 20% faster than system clock, 16ms gaps
+ // CachedClock: 10% faster than system clock, smaller gaps
+ clock.currentTimeMillis());
+
+ disruptor.publishEvent(info.translator);
+ }
+
+ private StackTraceElement location(String fqcnOfLogger) {
+ return Log4jLogEvent.calcLocation(fqcnOfLogger);
+ }
+
+ /**
+ * This method is called by the EventHandler that processes the
+ * RingBufferLogEvent in a separate thread.
+ *
+ * @param event the event to log
+ */
+ public void actualAsyncLog(RingBufferLogEvent event) {
+ Map<Property, Boolean> properties = config.loggerConfig.getProperties();
+ event.mergePropertiesIntoContextMap(properties,
+ config.config.getSubst());
+ config.logEvent(event);
+ }
+
+ public static void stop() {
+ Disruptor<RingBufferLogEvent> temp = disruptor;
+
+ // Must guarantee that publishing to the RingBuffer has stopped
+ // before we call disruptor.shutdown()
+ disruptor = null; // client code fails with NPE if log after stop = OK
+ temp.shutdown();
+
+ // wait up to 10 seconds for the ringbuffer to drain
+ RingBuffer<RingBufferLogEvent> ringBuffer = temp.getRingBuffer();
+ for (int i = 0; i < 20; i++) {
+ if (ringBuffer.hasAvailableCapacity(ringBuffer.getBufferSize())) {
+ break;
+ }
+ try {
+ Thread.sleep(500); // give ringbuffer some time to drain...
+ } catch (InterruptedException e) {
+ }
+ }
+ executor.shutdown(); // finally, kill the processor thread
+ }
+
+}
Added: logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLoggerContext.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLoggerContext.java?rev=1463078&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLoggerContext.java (added)
+++ logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLoggerContext.java Mon Apr 1 03:51:21 2013
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.async;
+
+import java.net.URI;
+
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.message.MessageFactory;
+
+// depends on LOG4J2-151
+public class AsyncLoggerContext extends LoggerContext {
+
+ public AsyncLoggerContext(String name) {
+ super(name);
+ }
+
+ public AsyncLoggerContext(String name, Object externalContext) {
+ super(name, externalContext);
+ }
+
+ public AsyncLoggerContext(String name, Object externalContext,
+ URI configLocn) {
+ super(name, externalContext, configLocn);
+ }
+
+ public AsyncLoggerContext(String name, Object externalContext,
+ String configLocn) {
+ super(name, externalContext, configLocn);
+ }
+
+ // @Override
+ protected Logger newInstance(LoggerContext ctx, String name,
+ MessageFactory messageFactory) {
+ return new AsyncLogger(ctx, name, messageFactory);
+ }
+
+ @Override
+ public void stop() {
+ AsyncLogger.stop();
+ super.stop();
+ }
+}
Added: logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLoggerContextSelector.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLoggerContextSelector.java?rev=1463078&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLoggerContextSelector.java (added)
+++ logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/AsyncLoggerContextSelector.java Mon Apr 1 03:51:21 2013
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.async;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.selector.ContextSelector;
+
+public class AsyncLoggerContextSelector implements ContextSelector {
+
+ private static final AsyncLoggerContext context = new AsyncLoggerContext(
+ "Default");
+
+ public LoggerContext getContext(String fqcn, ClassLoader loader,
+ boolean currentContext) {
+ return context;
+ }
+
+ public List<LoggerContext> getLoggerContexts() {
+ List<LoggerContext> list = new ArrayList<LoggerContext>();
+ list.add(context);
+ return Collections.unmodifiableList(list);
+ }
+
+ public LoggerContext getContext(String fqcn, ClassLoader loader,
+ boolean currentContext, URI configLocation) {
+ return context;
+ }
+
+}
Added: logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/CachedClock.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/CachedClock.java?rev=1463078&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/CachedClock.java (added)
+++ logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/CachedClock.java Mon Apr 1 03:51:21 2013
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.async;
+
+import com.lmax.disruptor.util.Util;
+
+
+public class CachedClock implements Clock {
+ private static CachedClock instance = new CachedClock();
+ private volatile long millis = System.currentTimeMillis();
+ private volatile short count = 0;
+ private final Thread updater = new Thread("Clock Updater Thread") {
+ public void run() {
+ while (true) {
+ long time = System.currentTimeMillis();
+ millis = time;
+ Util.getUnsafe().park(true, time + 1); // abs (millis)
+ // Util.getUnsafe().park(false, 1000 * 1000);// relative(nanos)
+ }
+ }
+ };
+
+ public static CachedClock instance() {
+ return instance;
+ }
+
+ private CachedClock() {
+ updater.setDaemon(true);
+ updater.start();
+ }
+
+ // @Override
+ public long currentTimeMillis() {
+
+ // improve granularity: also update time field every 1024 calls.
+ // (the bit fiddling means we don't need to worry about overflows)
+ if ((++count & 0x3FF) == 0x3FF) {
+ millis = System.currentTimeMillis();
+ }
+ return millis;
+ }
+}
Added: logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/Clock.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/Clock.java?rev=1463078&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/Clock.java (added)
+++ logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/Clock.java Mon Apr 1 03:51:21 2013
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.async;
+
+public interface Clock {
+ long currentTimeMillis();
+}
Added: logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/ClockFactory.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/ClockFactory.java?rev=1463078&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/ClockFactory.java (added)
+++ logging/log4j/log4j2/trunk/log4j-async/src/main/java/org/apache/logging/log4j/async/ClockFactory.java Mon Apr 1 03:51:21 2013
@@ -0,0 +1,41 @@
+package org.apache.logging.log4j.async;
+
+import org.apache.logging.log4j.status.StatusLogger;
+
+public class ClockFactory {
+
+ public static final String PROPERTY_NAME = "AsyncLogger.Clock";
+ //private static final Clock clock = createClock();
+
+ public static Clock getClock() {
+ return createClock();
+ }
+
+ private static Clock createClock() {
+ final StatusLogger LOGGER = StatusLogger.getLogger();
+ String userRequest = System.getProperty(PROPERTY_NAME);
+ if (userRequest == null || "SystemClock".equals(userRequest)) {
+ LOGGER.debug("Using default SystemClock for timestamps");
+ return new SystemClock();
+ }
+ if ("org.apache.logging.log4j.async.CachedClock".equals(userRequest)
+ || "CachedClock".equals(userRequest)) {
+ LOGGER.debug("Using specified CachedClock for timestamps");
+ return CachedClock.instance();
+ }
+ if ("org.apache.logging.log4j.async.CoarseCachedClock"
+ .equals(userRequest) || "CoarseCachedClock".equals(userRequest)) {
+ LOGGER.debug("Using specified CoarseCachedClock for timestamps");
+ return CoarseCachedClock.instance();
+ }
+ try {
+ Clock result = (Clock) Class.forName(userRequest).newInstance();
+ LOGGER.debug("Using {} for timestamps", userRequest);
+ return result;
+ } catch (Exception e) {
+ String fmt = "Could not create {}: {}, using default SystemClock for timestamps";
+ LOGGER.error(fmt, userRequest, e);
+ return new SystemClock();
+ }
+ }
+}