Repository: logging-log4j2 Updated Branches: refs/heads/master 9e59afe7a -> 05aef39ab
LOG4J2-1080 added unit test for AsyncAppender usage of AsyncEventRouter Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/00a51fc8 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/00a51fc8 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/00a51fc8 Branch: refs/heads/master Commit: 00a51fc825e7cc4722b039c5d749a45823ccb753 Parents: 759fa37 Author: rpopma <[email protected]> Authored: Sat May 7 02:57:38 2016 +0900 Committer: rpopma <[email protected]> Committed: Sat May 7 02:57:38 2016 +0900 ---------------------------------------------------------------------- .../appender/AsyncAppenderEventRouterTest.java | 114 +++++++++++++++++++ .../log4j/test/appender/BlockingAppender.java | 61 ++++++++++ .../test/resources/log4j-asynch-queue-full.xml | 38 +++++++ 3 files changed, 213 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/00a51fc8/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderEventRouterTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderEventRouterTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderEventRouterTest.java new file mode 100644 index 0000000..3e54764 --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderEventRouterTest.java @@ -0,0 +1,114 @@ +/* + * 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 java.util.concurrent.atomic.AtomicLong; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.async.DefaultAsyncEventRouter; +import org.apache.logging.log4j.core.async.EventRoute; +import org.apache.logging.log4j.junit.LoggerContextRule; +import org.apache.logging.log4j.test.appender.BlockingAppender; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Tests the AsyncAppender (LOG4J2-1080) event routing logic: + * <pre> + * If not BLOCKING, then offer the event to the queue and send to error appender if queue full. + * If BLOCKING, then (LOG4J2-471) + * if queue full (non-blocking call to queue.offer(event) failed) then + * if thread==backgroundThread delegate to event router + * else queue.add(event) // blocking call + * </pre> + */ +public class AsyncAppenderEventRouterTest { + private static final String CONFIG = "log4j-asynch-queue-full.xml"; + static { + // this must be set before the Log4j context initializes + System.setProperty("log4j2.AsyncEventRouter", CountingAsyncEventRouter.class.getName()); + } + + @AfterClass + public static void afterClass() { + System.clearProperty("log4j2.AsyncEventRouter"); + } + + @ClassRule + public static LoggerContextRule context = new LoggerContextRule(CONFIG); + + private BlockingAppender blockingAppender; + private AsyncAppender asyncAppender; + + @Before + public void before() throws Exception { + blockingAppender = (BlockingAppender) context.getAppender("Block"); + asyncAppender = (AsyncAppender) context.getAppender("Async"); + } + + @After + public void after() { +// blockingAppender.running = false; + } + + @Test + public void testRouter() throws Exception { + final Logger logger = LogManager.getLogger(AsyncAppenderEventRouterTest.class); + + assertEquals(3, asyncAppender.getQueueCapacity()); + logger.error("event 1 - gets taken off the queue"); + logger.warn("event 2"); + logger.info("event 3"); + logger.info("event 4 - now the queue is full"); + assertEquals("queue remaining capacity", 0, asyncAppender.getQueueRemainingCapacity()); + assertEquals("EventRouter invocations", 0, CountingAsyncEventRouter.queueFull.get()); + + Thread release = new Thread("AsyncAppenderReleaser") { + public void run() { + while (CountingAsyncEventRouter.queueFull.get() == 0) { + try { + Thread.sleep(10L); + } catch (InterruptedException ignored) { + //ignored + } + } + blockingAppender.running = false; + } + }; + release.setDaemon(true); + release.start(); + logger.fatal("this blocks until queue space available"); + assertEquals(1, CountingAsyncEventRouter.queueFull.get()); + } + + public static class CountingAsyncEventRouter extends DefaultAsyncEventRouter { + static AtomicLong queueFull = new AtomicLong(); + @Override + public EventRoute getRoute(long backgroundThreadId, Level level) { + queueFull.incrementAndGet(); + return EventRoute.ENQUEUE; + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/00a51fc8/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/BlockingAppender.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/BlockingAppender.java b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/BlockingAppender.java new file mode 100644 index 0000000..1564317 --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/BlockingAppender.java @@ -0,0 +1,61 @@ +/* + * 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.test.appender; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LoggingException; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.appender.AbstractAppender; +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.PluginFactory; +import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required; + +/** + * + */ +@Plugin(name="Block", category ="Core", elementType="appender", printObject=true) +public class BlockingAppender extends AbstractAppender { + public volatile boolean running = true; + + private BlockingAppender(final String name) { + super(name, null, null, false); + } + + @Override + public void append(final LogEvent event) { + while (running) { + try { + Thread.sleep(10L); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); // set interrupt status + } + } + } + @Override + public void stop() { + running = false; + super.stop(); + } + + @PluginFactory + public static BlockingAppender createAppender( + @PluginAttribute("name") @Required(message = "A name for the Appender must be specified") final String name) { + return new BlockingAppender(name); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/00a51fc8/log4j-core/src/test/resources/log4j-asynch-queue-full.xml ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j-asynch-queue-full.xml b/log4j-core/src/test/resources/log4j-asynch-queue-full.xml new file mode 100644 index 0000000..1495a3b --- /dev/null +++ b/log4j-core/src/test/resources/log4j-asynch-queue-full.xml @@ -0,0 +1,38 @@ +<?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="RoutingTest"> + + <Appenders> + <Console name="STDOUT"> + <PatternLayout pattern="%m%n"/> + </Console> + <Block name="Block"> + </Block> + <Async name="Async" bufferSize="3" includeLocation="false" error-ref="STDOUT"> + <AppenderRef ref="Block"/> + </Async> + </Appenders> + + <Loggers> + <Root level="debug"> + <AppenderRef ref="Async"/> + </Root> + </Loggers> + +</Configuration> \ No newline at end of file
