[
https://issues.apache.org/jira/browse/LOG4J2-493?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14970543#comment-14970543
]
Remko Popma commented on LOG4J2-493:
------------------------------------
{code}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
index 872c01d..6605129 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
@@ -74,7 +74,7 @@
*/
private volatile Configuration configuration = new DefaultConfiguration();
private Object externalContext;
- private final String contextName;
+ private String contextName;
private volatile URI configLocation;
private Cancellable shutdownCallback;
@@ -318,6 +318,16 @@
public String getName() {
return contextName;
}
+
+ /**
+ * Sets the name.
+ *
+ * @param name the new LoggerContext name
+ * @throws NullPointerException if the specified name is {@code null}
+ */
+ public void setName(final String name) {
+ contextName = Objects.requireNonNull(name);
+ }
/**
* Sets the external context.
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java
index 6636eba..1efdd18 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java
@@ -116,22 +116,23 @@
disruptor.handleEventsWith(handlers);
LOGGER.debug(
- "Starting AsyncLoggerConfig disruptor with ringbuffer size={},
waitStrategy={}, exceptionHandler={}...",
+ "Starting AsyncLoggerConfig disruptor with ringbufferSize={},
waitStrategy={}, exceptionHandler={}...",
disruptor.getRingBuffer().getBufferSize(),
waitStrategy.getClass().getSimpleName(), errorHandler);
disruptor.start();
}
private static WaitStrategy createWaitStrategy() {
final String strategy =
System.getProperty("AsyncLoggerConfig.WaitStrategy");
- LOGGER.trace("property AsyncLoggerConfig.WaitStrategy={}", strategy);
- if ("Sleep".equals(strategy)) {
- return new SleepingWaitStrategy();
- } else if ("Yield".equals(strategy)) {
- return new YieldingWaitStrategy();
- } else if ("Block".equals(strategy)) {
- return new BlockingWaitStrategy();
+ if (strategy != null) {
+ LOGGER.trace("property AsyncLoggerConfig.WaitStrategy={}",
strategy);
+ if ("Sleep".equals(strategy)) {
+ return new SleepingWaitStrategy();
+ } else if ("Yield".equals(strategy)) {
+ return new YieldingWaitStrategy();
+ } else if ("Block".equals(strategy)) {
+ return new BlockingWaitStrategy();
+ }
}
- LOGGER.trace("AsyncLoggerConfigHelper disruptor event handler uses
BlockingWaitStrategy");
return new BlockingWaitStrategy();
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContext.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContext.java
index 4efd7cc..70c3568 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContext.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContext.java
@@ -21,8 +21,10 @@
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.DefaultConfiguration;
import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
import org.apache.logging.log4j.message.MessageFactory;
+import org.apache.logging.log4j.status.StatusLogger;
/**
* {@code LoggerContext} that creates {@code AsyncLogger} objects.
@@ -57,6 +59,12 @@
protected Logger newInstance(final LoggerContext ctx, final String name,
final MessageFactory messageFactory) {
return new AsyncLogger(ctx, name, messageFactory, helper);
}
+
+ @Override
+ public void setName(final String name) {
+ super.setName("AsyncContext[" + name + "]");
+ helper.setContextName(name);
+ }
/*
* (non-Javadoc)
@@ -65,7 +73,7 @@
*/
@Override
public void start() {
- helper.start();
+ maybeStartHelper(getConfiguration());
super.start();
}
@@ -76,10 +84,21 @@
*/
@Override
public void start(Configuration config) {
- helper.start();
+ maybeStartHelper(config);
super.start(config);
}
+ private void maybeStartHelper(Configuration config) {
+ // If no log4j configuration was found, there are no loggers
+ // and there is no point in starting the disruptor (which takes up
+ // significant memory and starts a thread).
+ if (config instanceof DefaultConfiguration) {
+ StatusLogger.getLogger().debug("[{}] Not starting Disruptor for
DefaultConfiguration.", getName());
+ } else {
+ helper.start();
+ }
+ }
+
@Override
public void stop() {
helper.stop(); // first stop Disruptor
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContextSelector.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContextSelector.java
index 4d739e3..c9fc58b 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContextSelector.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContextSelector.java
@@ -25,6 +25,8 @@
/**
* {@code ContextSelector} that manages {@code AsyncLoggerContext} instances.
+ * <p>
+ * As of version 2.5, this class extends ClassLoaderContextSelector for better
web app support.
*/
public class AsyncLoggerContextSelector extends ClassLoaderContextSelector {
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerHelper.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerHelper.java
index 027fa0d..5c90eae 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerHelper.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerHelper.java
@@ -41,14 +41,14 @@
* life cycle of the context. The AsyncLoggerHelper of the context is shared
by all AsyncLogger objects created by that
* AsyncLoggerContext.
*/
-public class AsyncLoggerHelper {
+class AsyncLoggerHelper {
private static final int SLEEP_MILLIS_BETWEEN_DRAIN_ATTEMPTS = 50;
private static final int MAX_DRAIN_ATTEMPTS_BEFORE_SHUTDOWN = 200;
private static final int RINGBUFFER_MIN_SIZE = 128;
private static final int RINGBUFFER_DEFAULT_SIZE = 256 * 1024;
private static final StatusLogger LOGGER = StatusLogger.getLogger();
- private final String contextName;
+ private String contextName;
private ExecutorService executor;
private volatile Disruptor<RingBufferLogEvent> disruptor;
@@ -58,6 +58,10 @@
public String getContextName() {
return contextName;
+ }
+
+ public void setContextName(String name) {
+ contextName = name;
}
Disruptor<RingBufferLogEvent> getDisruptor() {
@@ -77,18 +81,22 @@
LOGGER.trace("[{}] AsyncLoggerHelper creating new disruptor.",
contextName);
final int ringBufferSize = calculateRingBufferSize();
final WaitStrategy waitStrategy = createWaitStrategy();
- executor = Executors.newSingleThreadExecutor(new
DaemonThreadFactory(contextName + "-Logger-"));
+ executor = Executors.newSingleThreadExecutor(new
DaemonThreadFactory("AsyncLogger[" + contextName + "]"));
Info.initExecutorThreadInstance(executor);
disruptor = new Disruptor<>(RingBufferLogEvent.FACTORY,
ringBufferSize, executor, ProducerType.MULTI,
waitStrategy);
- disruptor.handleExceptionsWith(getExceptionHandler());
+
+ final ExceptionHandler<RingBufferLogEvent> errorHandler =
getExceptionHandler();
+ disruptor.handleExceptionsWith(errorHandler);
final RingBufferLogEventHandler[] handlers = {new
RingBufferLogEventHandler()};
disruptor.handleEventsWith(handlers);
- LOGGER.debug("[{}] Starting AsyncLogger disruptor with ringbuffer size
{}...", contextName, disruptor
- .getRingBuffer().getBufferSize());
+ LOGGER.debug(
+ "[{}] Starting AsyncLogger disruptor with
ringbufferSize={}, waitStrategy={}, exceptionHandler={}...",
+ contextName, disruptor.getRingBuffer().getBufferSize(),
waitStrategy.getClass().getSimpleName(),
+ errorHandler);
disruptor.start();
}
@@ -113,22 +121,22 @@
private WaitStrategy createWaitStrategy() {
final String strategy =
PropertiesUtil.getProperties().getStringProperty("AsyncLogger.WaitStrategy");
- LOGGER.debug("[{}] property AsyncLogger.WaitStrategy={}", contextName,
strategy);
- if ("Sleep".equals(strategy)) {
- return new SleepingWaitStrategy();
- } else if ("Yield".equals(strategy)) {
- return new YieldingWaitStrategy();
- } else if ("Block".equals(strategy)) {
- return new BlockingWaitStrategy();
+ if (strategy != null) {
+ LOGGER.trace("[{}] property AsyncLogger.WaitStrategy={}",
contextName, strategy);
+ if ("Sleep".equals(strategy)) {
+ return new SleepingWaitStrategy();
+ } else if ("Yield".equals(strategy)) {
+ return new YieldingWaitStrategy();
+ } else if ("Block".equals(strategy)) {
+ return new BlockingWaitStrategy();
+ }
}
- LOGGER.debug("[{}] disruptor event handler uses BlockingWaitStrategy",
contextName);
return new BlockingWaitStrategy();
}
private ExceptionHandler<RingBufferLogEvent> getExceptionHandler() {
final String cls =
PropertiesUtil.getProperties().getStringProperty("AsyncLogger.ExceptionHandler");
if (cls == null) {
- LOGGER.debug("[{}] No AsyncLogger.ExceptionHandler specified",
contextName);
return null;
}
try {
@@ -163,7 +171,8 @@
* @return a new {@code RingBufferAdmin} that instruments the ringbuffer
*/
public RingBufferAdmin createRingBufferAdmin(final String contextName) {
- return RingBufferAdmin.forAsyncLogger(disruptor.getRingBuffer(),
contextName);
+ final RingBuffer<RingBufferLogEvent> ring = disruptor == null ? null :
disruptor.getRingBuffer();
+ return RingBufferAdmin.forAsyncLogger(ring, contextName);
}
/**
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
index 5c6ebfe..f54fa2d 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
@@ -222,6 +222,9 @@
if (externalContext != null && ctx.getExternalContext() == null) {
ctx.setExternalContext(externalContext);
}
+ if (name != null) {
+ ctx.setName(name);
+ }
if (ctx.getState() == LifeCycle.State.INITIALIZED) {
if (configLocation != null || name != null) {
ContextAnchor.THREAD_CONTEXT.set(ctx);
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/RingBufferAdmin.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/RingBufferAdmin.java
index 71c14f7..15a9e56 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/RingBufferAdmin.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/RingBufferAdmin.java
@@ -16,8 +16,6 @@
*/
package org.apache.logging.log4j.core.jmx;
-import java.util.Objects;
-
import javax.management.ObjectName;
import com.lmax.disruptor.RingBuffer;
@@ -45,7 +43,7 @@
}
protected RingBufferAdmin(final RingBuffer<?> ringBuffer, final String
mbeanName) {
- this.ringBuffer = Objects.requireNonNull(ringBuffer, "ringbuffer");
+ this.ringBuffer = ringBuffer;
try {
objectName = new ObjectName(mbeanName);
} catch (final Exception e) {
@@ -55,12 +53,12 @@
@Override
public long getBufferSize() {
- return ringBuffer.getBufferSize();
+ return ringBuffer == null ? 0 : ringBuffer.getBufferSize();
}
@Override
public long getRemainingCapacity() {
- return ringBuffer.remainingCapacity();
+ return ringBuffer == null ? 0 : ringBuffer.remainingCapacity();
}
/**
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
index c4f596d..5baef72 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
@@ -174,7 +174,10 @@
if (ctx instanceof AsyncLoggerContext) {
final RingBufferAdmin rbmbean = ((AsyncLoggerContext)
ctx).createRingBufferAdmin();
- register(mbs, rbmbean, rbmbean.getObjectName());
+ if (rbmbean.getBufferSize() > 0) {
+ // don't register if Disruptor not started
(DefaultConfiguration: config not found)
+ register(mbs, rbmbean, rbmbean.getObjectName());
+ }
}
// register the status logger and the context selector
{code}
> Problem with AsyncLogger when web app is deployed/undeployed multiple times
> ---------------------------------------------------------------------------
>
> Key: LOG4J2-493
> URL: https://issues.apache.org/jira/browse/LOG4J2-493
> Project: Log4j 2
> Issue Type: Bug
> Components: Core
> Affects Versions: 2.0-beta9, 2.0-rc1
> Environment: tomcat 7.0.42
> Reporter: Kireet Reddy
> Assignee: Remko Popma
> Labels: Async
> Fix For: 2.5
>
>
> |_This ticket tracks Async Logger issues in Tomcat when making all loggers
> async with LoggerContextSelector system property. For Tomcat issues with
> AsyncRoot/AsyncLogger in the configuration file, see LOG4J2-323._|
> When redeploying my application in tomcat multiple times, I get an exception:
> {code}
> Exception in thread "Thread-29" java.lang.NullPointerException
> at
> org.apache.logging.log4j.core.async.AsyncLogger.stop(AsyncLogger.java:249)
> at
> org.apache.logging.log4j.core.async.AsyncLoggerContext.stop(AsyncLoggerContext.java:56)
> at
> org.apache.logging.log4j.core.LoggerContext$ShutdownThread.run(LoggerContext.java:437)
> {code}
> This seems to be due to the fact that some initialization code happens in the
> class initializer but is undone in the stop() method which is called during
> webapp undeployment. This causes issues because in this case the log4j jar is
> loaded by the shared classloader ($catalina.home/lib) rather than the webapp
> classloader. This means the AsyncLogger class is not re-created during webapp
> deployment.
> I am using this structure because I have many 3rd party libraries and want to
> keep redeployments lightweight.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]