You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2020/06/29 00:39:52 UTC
[logging-log4j2] branch master updated: LOG4J2-2867 - Obtain
ContextDataProviders asynchronously
This is an automated email from the ASF dual-hosted git repository.
rgoers pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/master by this push:
new f14654a LOG4J2-2867 - Obtain ContextDataProviders asynchronously
f14654a is described below
commit f14654af0bba3fc1382682f538e7ef1bea814c11
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Sun Jun 28 17:39:33 2020 -0700
LOG4J2-2867 - Obtain ContextDataProviders asynchronously
---
.../apache/logging/log4j/core/LoggerContext.java | 5 +-
.../log4j/core/impl/ThreadContextDataInjector.java | 48 +++++++++++----
.../org/apache/logging/log4j/core/LoggingTest.java | 69 ++++++++++++++++++++++
3 files changed, 111 insertions(+), 11 deletions(-)
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
index 8b181d0..0efea61 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
@@ -27,6 +27,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -43,6 +44,7 @@ import org.apache.logging.log4j.core.config.DefaultConfiguration;
import org.apache.logging.log4j.core.config.NullConfiguration;
import org.apache.logging.log4j.core.config.Reconfigurable;
import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.impl.ThreadContextDataInjector;
import org.apache.logging.log4j.core.jmx.Server;
import org.apache.logging.log4j.core.util.Cancellable;
import org.apache.logging.log4j.core.util.ExecutorServices;
@@ -59,7 +61,6 @@ import org.apache.logging.log4j.spi.Terminable;
import org.apache.logging.log4j.spi.ThreadContextMapFactory;
import org.apache.logging.log4j.util.PropertiesUtil;
-
/**
* The LoggerContext is the anchor for the logging system. It maintains a list of all the loggers requested by
* applications and a reference to the Configuration. The Configuration will contain the configured loggers, appenders,
@@ -136,6 +137,7 @@ public class LoggerContext extends AbstractLifeCycle
externalMap.put(EXTERNAL_CONTEXT_KEY, externalContext);
}
this.configLocation = configLocn;
+ CompletableFuture.runAsync(ThreadContextDataInjector::initServiceProviders);
}
/**
@@ -164,6 +166,7 @@ public class LoggerContext extends AbstractLifeCycle
} else {
configLocation = null;
}
+ CompletableFuture.runAsync(ThreadContextDataInjector::initServiceProviders);
}
public void addShutdownListener(LoggerContextShutdownAware listener) {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java
index 5ce7819..ace66ef 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java
@@ -23,6 +23,8 @@ import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
@@ -60,6 +62,39 @@ public class ThreadContextDataInjector {
public static Collection<ContextDataProvider> contextDataProviders =
new ConcurrentLinkedDeque<>();
+ private static volatile List<ContextDataProvider> serviceProviders = null;
+ private static final Lock providerLock = new ReentrantLock();
+
+ public static void initServiceProviders() {
+ if (serviceProviders == null) {
+ providerLock.lock();
+ try {
+ if (serviceProviders == null) {
+ serviceProviders = getServiceProviders();
+ }
+ } finally {
+ providerLock.unlock();
+ }
+ }
+ }
+
+ private static List<ContextDataProvider> getServiceProviders() {
+ List<ContextDataProvider> providers = new ArrayList<>();
+ for (final ClassLoader classLoader : LoaderUtil.getClassLoaders()) {
+ try {
+ for (final ContextDataProvider provider : ServiceLoader.load(ContextDataProvider.class, classLoader)) {
+ if (providers.stream().noneMatch((p) -> p.getClass().isAssignableFrom(provider.getClass()))) {
+ providers.add(provider);
+ }
+ }
+ } catch (final Throwable ex) {
+ LOGGER.debug("Unable to access Context Data Providers {}", ex.getMessage());
+ }
+ }
+ return providers;
+ }
+
+
/**
* Default {@code ContextDataInjector} for the legacy {@code Map<String, String>}-based ThreadContext (which is
* also the ThreadContext implementation used for web applications).
@@ -248,17 +283,10 @@ public class ThreadContextDataInjector {
}
private static List<ContextDataProvider> getProviders() {
+ initServiceProviders();
final List<ContextDataProvider> providers = new ArrayList<>(contextDataProviders);
- for (final ClassLoader classLoader : LoaderUtil.getClassLoaders()) {
- try {
- for (final ContextDataProvider provider : ServiceLoader.load(ContextDataProvider.class, classLoader)) {
- if (providers.stream().noneMatch((p) -> p.getClass().isAssignableFrom(provider.getClass()))) {
- providers.add(provider);
- }
- }
- } catch (final Throwable ex) {
- LOGGER.debug("Unable to access Context Data Providers {}", ex.getMessage());
- }
+ if (serviceProviders != null) {
+ providers.addAll(serviceProviders);
}
return providers;
}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggingTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggingTest.java
new file mode 100644
index 0000000..1365a08
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggingTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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;
+
+import java.util.List;
+
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.apache.logging.log4j.util.Timer;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class LoggingTest {
+
+ private static final String CONFIG = "log4j-list.xml";
+
+ @Rule
+ public final TestName testName = new TestName();
+ private ListAppender list;
+
+
+ @Rule
+ public LoggerContextRule context = new LoggerContextRule(CONFIG);
+
+ private void assertEventCount(final List<LogEvent> events, final int expected) {
+ assertEquals("Incorrect number of events.", expected, events.size());
+ }
+
+ @Before
+ public void before() {
+ logger = context.getLogger("LoggerTest");
+ }
+
+ org.apache.logging.log4j.Logger logger;
+
+ @Test
+ public void logTime() {
+ Timer timer = new Timer("initial");
+ timer.start();
+ logger.info("This is a test");
+ System.out.println(timer.stop());
+ timer = new Timer("more", 100);
+/* timer.start();
+ for (int i=0; i < 100; ++i) {
+ logger.info("This is another test");
+ }
+ System.out.println(timer.stop());*/
+ }
+}
+