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
