You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ck...@apache.org on 2021/03/24 19:22:44 UTC
[logging-log4j2] 01/02: LOG4J2-2940: Implement
BasicAsyncLoggerContextSelector
This is an automated email from the ASF dual-hosted git repository.
ckozak pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 12bd5bf77939f276cf4bfbcb867085bf0dfdd568
Author: Carter Kozak <ck...@apache.org>
AuthorDate: Mon Mar 22 14:52:11 2021 -0400
LOG4J2-2940: Implement BasicAsyncLoggerContextSelector
The BasicAsyncLoggerContextSelector is equivalent to the
AsyncLoggerContextSelector without ClassLoader introspection
and associated overhead.
---
.../async/BasicAsyncLoggerContextSelector.java | 84 ++++++++++++++++
.../log4j/core/selector/CoreContextSelectors.java | 8 +-
.../async/BasicAsyncLoggerContextSelectorTest.java | 107 +++++++++++++++++++++
src/changes/changes.xml | 5 +
4 files changed, 203 insertions(+), 1 deletion(-)
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/BasicAsyncLoggerContextSelector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/BasicAsyncLoggerContextSelector.java
new file mode 100644
index 0000000..90ce160
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/BasicAsyncLoggerContextSelector.java
@@ -0,0 +1,84 @@
+/*
+ * 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.async;
+
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.impl.ContextAnchor;
+import org.apache.logging.log4j.core.selector.ContextSelector;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Returns either this Thread's context or the default {@link AsyncLoggerContext}.
+ * Single-application instances should prefer this implementation over the {@link AsyncLoggerContextSelector}
+ * due the the reduced overhead avoiding classloader lookups.
+ */
+public class BasicAsyncLoggerContextSelector implements ContextSelector {
+
+ private static final AsyncLoggerContext CONTEXT = new AsyncLoggerContext("AsyncDefault");
+
+ @Override
+ public void shutdown(String fqcn, ClassLoader loader, boolean currentContext, boolean allContexts) {
+ LoggerContext ctx = getContext(fqcn, loader, currentContext);
+ if (ctx != null && ctx.isStarted()) {
+ ctx.stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ @Override
+ public boolean hasContext(String fqcn, ClassLoader loader, boolean currentContext) {
+ LoggerContext ctx = getContext(fqcn, loader, currentContext);
+ return ctx != null && ctx.isStarted();
+ }
+
+ @Override
+ public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
+ final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
+ return ctx != null ? ctx : CONTEXT;
+ }
+
+
+ @Override
+ public LoggerContext getContext(
+ final String fqcn,
+ final ClassLoader loader,
+ final boolean currentContext,
+ final URI configLocation) {
+ final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
+ return ctx != null ? ctx : CONTEXT;
+ }
+
+ @Override
+ public void removeContext(final LoggerContext context) {
+ // does not remove anything
+ }
+
+ @Override
+ public boolean isClassLoaderDependent() {
+ return false;
+ }
+
+ @Override
+ public List<LoggerContext> getLoggerContexts() {
+ return Collections.singletonList(CONTEXT);
+ }
+
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/CoreContextSelectors.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/CoreContextSelectors.java
index 1077e5a..2ee6b0d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/CoreContextSelectors.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/CoreContextSelectors.java
@@ -17,9 +17,15 @@
package org.apache.logging.log4j.core.selector;
import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector;
+import org.apache.logging.log4j.core.async.BasicAsyncLoggerContextSelector;
public class CoreContextSelectors {
- public static final Class<?>[] CLASSES = new Class<?>[] { ClassLoaderContextSelector.class, BasicContextSelector.class, AsyncLoggerContextSelector.class };
+ public static final Class<?>[] CLASSES = new Class<?>[] {
+ ClassLoaderContextSelector.class,
+ BasicContextSelector.class,
+ AsyncLoggerContextSelector.class,
+ BasicAsyncLoggerContextSelector.class
+ };
}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/BasicAsyncLoggerContextSelectorTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/BasicAsyncLoggerContextSelectorTest.java
new file mode 100644
index 0000000..823cc3f
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/BasicAsyncLoggerContextSelectorTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.async;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.categories.AsyncLoggers;
+import org.apache.logging.log4j.core.LifeCycle;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.util.Constants;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+@Category(AsyncLoggers.class)
+public class BasicAsyncLoggerContextSelectorTest {
+
+ private static final String FQCN = BasicAsyncLoggerContextSelectorTest.class.getName();
+
+ @BeforeClass
+ public static void beforeClass() {
+ System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
+ BasicAsyncLoggerContextSelector.class.getName());
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ System.clearProperty(Constants.LOG4J_CONTEXT_SELECTOR);
+ }
+
+ @Test
+ public void testContextReturnsAsyncLoggerContext() {
+ final BasicAsyncLoggerContextSelector selector = new BasicAsyncLoggerContextSelector();
+ final LoggerContext context = selector.getContext(FQCN, null, false);
+
+ assertTrue(context instanceof AsyncLoggerContext);
+ }
+
+ @Test
+ public void testContext2ReturnsAsyncLoggerContext() {
+ final BasicAsyncLoggerContextSelector selector = new BasicAsyncLoggerContextSelector();
+ final LoggerContext context = selector.getContext(FQCN, null, false, null);
+
+ assertTrue(context instanceof AsyncLoggerContext);
+ }
+
+ @Test
+ public void testLoggerContextsReturnsAsyncLoggerContext() {
+ final BasicAsyncLoggerContextSelector selector = new BasicAsyncLoggerContextSelector();
+
+ List<LoggerContext> list = selector.getLoggerContexts();
+ assertEquals(1, list.size());
+ assertTrue(list.get(0) instanceof AsyncLoggerContext);
+
+ selector.getContext(FQCN, null, false);
+
+ list = selector.getLoggerContexts();
+ assertEquals(1, list.size());
+ assertTrue(list.get(0) instanceof AsyncLoggerContext);
+ }
+
+ @Test
+ public void testContextNameIsAsyncDefault() {
+ final BasicAsyncLoggerContextSelector selector = new BasicAsyncLoggerContextSelector();
+ final LoggerContext context = selector.getContext(FQCN, null, false);
+ assertEquals("AsyncDefault" , context.getName());
+ }
+
+ @Test
+ public void testDependentOnClassLoader() {
+ final BasicAsyncLoggerContextSelector selector = new BasicAsyncLoggerContextSelector();
+ assertFalse(selector.isClassLoaderDependent());
+ }
+
+ @Test
+ public void testFactoryIsNotDependentOnClassLoader() {
+ assertFalse(LogManager.getFactory().isClassLoaderDependent());
+ }
+
+ @Test
+ public void testLogManagerShutdown() {
+ LoggerContext context = (LoggerContext) LogManager.getContext();
+ assertEquals(LifeCycle.State.STARTED, context.getState());
+ LogManager.shutdown();
+ assertEquals(LifeCycle.State.STOPPED, context.getState());
+ }
+}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 13f9d7a..825222f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -47,6 +47,11 @@
basic context selectors to avoid the unnecessary overhead of walking the stack to
determine the caller's ClassLoader.
</action>
+ <action issue="LOG4J2-2940" dev="ckozak" type="add">
+ Add BasicAsyncLoggerContextSelector equivalent to AsyncLoggerContextSelector for
+ applications with a single LoggerContext. This selector avoids classloader lookup
+ overhead incurred by the existing AsyncLoggerContextSelector.
+ </action>
<action issue="LOG4J2-3041" dev="rgoers" type="update">
Allow a PatternSelector to be specified on GelfLayout.
</action>