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:29:07 UTC

[logging-log4j2] branch master updated (d819f0a -> 6027bae)

This is an automated email from the ASF dual-hosted git repository.

ckozak pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git.


    from d819f0a  LOG4J2-2940: Reduce StackWalker interactions accessing an slf4j logger instance
     new 702787e  LOG4J2-2940: Implement BasicAsyncLoggerContextSelector
     new 6027bae  BasicAsyncLoggerContextSelector documentation

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../BasicAsyncLoggerContextSelector.java}          |  33 +++----
 .../log4j/core/selector/CoreContextSelectors.java  |   8 +-
 .../async/BasicAsyncLoggerContextSelectorTest.java | 107 +++++++++++++++++++++
 src/changes/changes.xml                            |   5 +
 src/site/asciidoc/manual/async.adoc                |  10 +-
 src/site/asciidoc/manual/configuration.adoc        |   3 +
 6 files changed, 145 insertions(+), 21 deletions(-)
 copy log4j-core/src/main/java/org/apache/logging/log4j/core/{selector/BasicContextSelector.java => async/BasicAsyncLoggerContextSelector.java} (72%)
 create mode 100644 log4j-core/src/test/java/org/apache/logging/log4j/core/async/BasicAsyncLoggerContextSelectorTest.java

[logging-log4j2] 01/02: LOG4J2-2940: Implement BasicAsyncLoggerContextSelector

Posted by ck...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ckozak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 702787e1d37f9becec1751b819013e687e588bb5
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 3d8c3d8..3644802 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -186,6 +186,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>

[logging-log4j2] 02/02: BasicAsyncLoggerContextSelector documentation

Posted by ck...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ckozak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 6027bae51f85c9fc3415d404e4758dd0ccad0735
Author: Carter Kozak <ck...@apache.org>
AuthorDate: Tue Mar 23 21:33:15 2021 -0400

    BasicAsyncLoggerContextSelector documentation
---
 src/site/asciidoc/manual/async.adoc         | 10 +++++++---
 src/site/asciidoc/manual/configuration.adoc |  3 +++
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/site/asciidoc/manual/async.adoc b/src/site/asciidoc/manual/async.adoc
index c89921b..308f676 100644
--- a/src/site/asciidoc/manual/async.adoc
+++ b/src/site/asciidoc/manual/async.adoc
@@ -119,7 +119,8 @@ required._
 This is simplest to configure and gives the best performance. To make
 all loggers asynchronous, add the disruptor jar to the classpath and set
 the system property `log4j2.contextSelector` to
-`org.apache.logging.log4j.core.async.AsyncLoggerContextSelector`.
+`org.apache.logging.log4j.core.async.AsyncLoggerContextSelector` or
+`org.apache.logging.log4j.core.async.BasicAsyncLoggerContextSelector`.
 
 By default, link:#Location[location] is not passed to the I/O thread by
 asynchronous loggers. If one of your layouts or custom filters needs
@@ -134,6 +135,8 @@ A configuration that does not require location might look like:
 
 <!-- Don't forget to set system property
 -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
+or
+-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.BasicAsyncLoggerContextSelector
      to make all loggers asynchronous. -->
 
 <Configuration status="WARN">
@@ -153,9 +156,10 @@ A configuration that does not require location might look like:
 </Configuration>
 ----
 
-When `AsyncLoggerContextSelector` is used to make all loggers
+When `AsyncLoggerContextSelector` or
+`BasicAsyncLoggerContextSelector` is used to make all loggers
 asynchronous, make sure to use normal `<root>` and `<logger>` elements
-in the configuration. The AsyncLoggerContextSelector will ensure that
+in the configuration. The context selector will ensure that
 all loggers are asynchronous, using a mechanism that is different from
 what happens when you configure `<asyncRoot>` or `<asyncLogger>`. The
 latter elements are intended for mixing async with sync loggers. If you
diff --git a/src/site/asciidoc/manual/configuration.adoc b/src/site/asciidoc/manual/configuration.adoc
index 125a5b2..cb17098 100644
--- a/src/site/asciidoc/manual/configuration.adoc
+++ b/src/site/asciidoc/manual/configuration.adoc
@@ -1725,6 +1725,9 @@ circumstances. See link:logsep.html[Log Separation] for more details.
 Available context selector implementation classes: +
 `org.apache.logging.log4j.core.async .AsyncLoggerContextSelector` -
 makes link:async.html[all loggers asynchronous]. +
+`org.apache.logging.log4j.core.async .BasicAsyncLoggerContextSelector` -
+makes link:async.html[all loggers asynchronous] using a single shared
+AsyncLoggerContext. +
 `org.apache.logging.log4j.core.selector .BasicContextSelector` - creates
 a single shared LoggerContext. +
 `org.apache.logging.log4j.core.selector .ClassLoaderContextSelector` -