Repository: logging-log4j2
Updated Branches:
  refs/heads/master 2946d57aa -> 3f87e7acd


Possibility to set shutdown timeout on AsyncAppender (LOG4J-1012)


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/db31dad0
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/db31dad0
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/db31dad0

Branch: refs/heads/master
Commit: db31dad0cf3e2fa2ba695fc877a362365c36b05d
Parents: 6ad2d29
Author: Mikael StÃ¥ldal <[email protected]>
Authored: Mon Sep 28 18:32:59 2015 +0200
Committer: Mikael StÃ¥ldal <[email protected]>
Committed: Mon Sep 28 18:32:59 2015 +0200

----------------------------------------------------------------------
 .../log4j/core/appender/AsyncAppender.java      | 13 ++--
 .../AsyncAppenderShutdownTimeoutTest.java       | 51 ++++++++++++++++
 .../log4j/core/appender/HangingAppender.java    | 62 ++++++++++++++++++++
 .../resources/log4j-asynch-shutdownTimeout.xml  | 37 ++++++++++++
 4 files changed, 159 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/db31dad0/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java
index 0c0378c..7727278 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java
@@ -58,6 +58,7 @@ public final class AsyncAppender extends AbstractAppender {
     private final BlockingQueue<Serializable> queue;
     private final int queueSize;
     private final boolean blocking;
+    private final long shutdownTimeout;
     private final Configuration config;
     private final AppenderRef[] appenderRefs;
     private final String errorRef;
@@ -67,11 +68,12 @@ public final class AsyncAppender extends AbstractAppender {
 
     private AsyncAppender(final String name, final Filter filter, final 
AppenderRef[] appenderRefs,
             final String errorRef, final int queueSize, final boolean 
blocking, final boolean ignoreExceptions,
-            final Configuration config, final boolean includeLocation) {
+            final long shutdownTimeout, final Configuration config, final 
boolean includeLocation) {
         super(name, filter, null, ignoreExceptions);
         this.queue = new ArrayBlockingQueue<>(queueSize);
         this.queueSize = queueSize;
         this.blocking = blocking;
+        this.shutdownTimeout = shutdownTimeout;
         this.config = config;
         this.appenderRefs = appenderRefs;
         this.errorRef = errorRef;
@@ -115,7 +117,7 @@ public final class AsyncAppender extends AbstractAppender {
         LOGGER.trace("AsyncAppender stopping. Queue still has {} events.", 
queue.size());
         thread.shutdown();
         try {
-            thread.join();
+            thread.join(shutdownTimeout);
         } catch (final InterruptedException ex) {
             LOGGER.warn("Interrupted while stopping AsyncAppender {}", 
getName());
         }
@@ -191,6 +193,8 @@ public final class AsyncAppender extends AbstractAppender {
      * @param appenderRefs The Appenders to reference.
      * @param errorRef An optional Appender to write to if the queue is full 
or other errors occur.
      * @param blocking True if the Appender should wait when the queue is 
full. The default is true.
+     * @param shutdownTimeout How many milliseconds the Appender should wait 
to flush outstanding log events
+     *                        in the queue on shutdown. The default is zero 
which means to wait forever.
      * @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.
@@ -204,6 +208,7 @@ public final class AsyncAppender extends AbstractAppender {
     public static AsyncAppender createAppender(@PluginElement("AppenderRef") 
final AppenderRef[] appenderRefs,
             @PluginAttribute("errorRef") @PluginAliases("error-ref") final 
String errorRef,
             @PluginAttribute(value = "blocking", defaultBoolean = true) final 
boolean blocking,
+            @PluginAttribute(value = "shutdownTimeout", defaultLong = 0L) 
final long shutdownTimeout,
             @PluginAttribute(value = "bufferSize", defaultInt = 
DEFAULT_QUEUE_SIZE) final int size,
             @PluginAttribute("name") final String name,
             @PluginAttribute(value = "includeLocation", defaultBoolean = 
false) final boolean includeLocation,
@@ -217,8 +222,8 @@ public final class AsyncAppender extends AbstractAppender {
             LOGGER.error("No appender references provided to AsyncAppender 
{}", name);
         }
 
-        return new AsyncAppender(name, filter, appenderRefs, errorRef, size, 
blocking, ignoreExceptions, config,
-                includeLocation);
+        return new AsyncAppender(name, filter, appenderRefs, errorRef, size, 
blocking, ignoreExceptions,
+                shutdownTimeout, config, includeLocation);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/db31dad0/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderShutdownTimeoutTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderShutdownTimeoutTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderShutdownTimeoutTest.java
new file mode 100644
index 0000000..7b66a43
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderShutdownTimeoutTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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 org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class AsyncAppenderShutdownTimeoutTest {
+    private static final String CONFIG = "log4j-asynch-shutdownTimeout.xml";
+
+    @BeforeClass
+    public static void setupClass() {
+        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, 
CONFIG);
+    }
+
+    @AfterClass
+    public static void cleanupClass() {
+        System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
+    }
+
+    @Test(timeout = 2000)
+    public void shutdownTest() throws Exception {
+        final LoggerContext ctx = (LoggerContext)LogManager.getContext(false);
+        final Logger logger = ctx.getLogger("Logger");
+        logger.info("This is a test");
+        ctx.stop();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/db31dad0/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HangingAppender.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HangingAppender.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HangingAppender.java
new file mode 100644
index 0000000..a3ebbf0
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HangingAppender.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import 
org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
+
+import java.io.Serializable;
+
+@Plugin(name = "Hanging", category = "Core", elementType = "appender", 
printObject = true)
+public class HangingAppender extends AbstractAppender {
+
+    private static final long serialVersionUID = 1L;
+
+    private final long delay;
+
+    public HangingAppender(final String name, final long delay) {
+        super(name, null, null);
+        this.delay = delay;
+    }
+
+    @Override
+    public void append(final LogEvent event) {
+        try {
+            Thread.sleep(delay);
+        } catch (InterruptedException ignore) {
+            // ignore
+        }
+    }
+
+    @PluginFactory
+    public static HangingAppender createAppender(
+            @PluginAttribute("name")
+            @Required(message = "No name provided for HangingAppender")
+            final String name,
+            @PluginAttribute("delay") final long delay,
+            @PluginElement("Layout") final Layout<? extends Serializable> 
layout,
+            @PluginElement("Filter") final Filter filter) {
+        return new HangingAppender(name, delay);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/db31dad0/log4j-core/src/test/resources/log4j-asynch-shutdownTimeout.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-asynch-shutdownTimeout.xml 
b/log4j-core/src/test/resources/log4j-asynch-shutdownTimeout.xml
new file mode 100644
index 0000000..aa5cb57
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-asynch-shutdownTimeout.xml
@@ -0,0 +1,37 @@
+<?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="OFF" name="AsyncAppenderShutdownTimeoutTest">
+
+  <Appenders>
+    <Console name="STDOUT">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+    <Hanging name="Hanging" delay="10000"/>
+    <Async name="Async" shutdownTimeout="1000" error-ref="STDOUT">
+      <AppenderRef ref="Hanging"/>
+    </Async>
+  </Appenders>
+
+  <Loggers>
+    <Root level="debug">
+      <AppenderRef ref="Async"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
\ No newline at end of file

Reply via email to