This is an automated email from the ASF dual-hosted git repository. pkarwasz pushed a commit to branch ScopedContext-replace-with-interface in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 827dbe02b406af66e18178fb916d382d557b1a55 Author: Ralph Goers <[email protected]> AuthorDate: Thu Apr 4 08:14:49 2024 -0700 Move non-API classes to core --- .../org/apache/logging/log4j/test/TestLogger.java | 10 +- .../org/apache/logging/log4j/ScopedContext.java | 123 +++++++++++++-------- .../apache/logging/log4j/simple/SimpleLogger.java | 7 +- .../logging/log4j/spi/ContextDataProvider.java | 76 ------------- .../log4j/spi/ScopedContextDataProvider.java | 104 ----------------- .../logging/log4j/core/async/AsyncLogger.java | 2 +- .../core/async/RingBufferLogEventTranslator.java | 2 +- .../log4j/core/filter/DynamicThresholdFilter.java | 4 +- .../log4j/core/filter/ThreadContextMapFilter.java | 2 +- .../logging/log4j/core/impl}/ContextData.java | 5 +- .../logging/log4j/core/impl/Log4jLogEvent.java | 1 - .../log4j/core/impl/ReusableLogEventFactory.java | 1 - .../log4j/core/impl/ScopedContextDataProvider.java | 27 +++-- .../log4j/core/impl/ThreadContextDataInjector.java | 11 +- .../log4j/core/impl/ThreadContextDataProvider.java | 15 +++ .../log4j/core/lookup/ContextMapLookup.java | 2 +- .../apache/logging/log4j/core/osgi/Activator.java | 6 +- .../log4j/core/util/ContextDataProvider.java | 52 ++++++++- 18 files changed, 190 insertions(+), 260 deletions(-) diff --git a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/TestLogger.java b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/TestLogger.java index b308434cfc..5f1fb02de7 100644 --- a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/TestLogger.java +++ b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/TestLogger.java @@ -23,9 +23,10 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.ScopedContext; +import org.apache.logging.log4j.ThreadContext; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.spi.AbstractLogger; @@ -80,8 +81,11 @@ public class TestLogger extends AbstractLogger { sb.append(' '); } sb.append(message.getFormattedMessage()); - final Map<String, String> mdc = new HashMap<>(ContextData.size()); - ContextData.addAll(mdc); + Map<String, ScopedContext.Renderable> contextMap = ScopedContext.getContextMap(); + final Map<String, String> mdc = new HashMap<>(ThreadContext.getImmutableContext()); + if (contextMap != null && !contextMap.isEmpty()) { + contextMap.forEach((key, value) -> mdc.put(key, value.render())); + } if (!mdc.isEmpty()) { sb.append(' '); sb.append(mdc); diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/ScopedContext.java b/log4j-api/src/main/java/org/apache/logging/log4j/ScopedContext.java index 67e2ba97fd..4081be5629 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/ScopedContext.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/ScopedContext.java @@ -16,7 +16,9 @@ */ package org.apache.logging.log4j; +import java.util.ArrayDeque; import java.util.Collections; +import java.util.Deque; import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -25,7 +27,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.function.Supplier; -import org.apache.logging.log4j.spi.ScopedContextDataProvider; import org.apache.logging.log4j.status.StatusLogger; /** @@ -52,6 +53,48 @@ public class ScopedContext { public static final Logger LOGGER = StatusLogger.getLogger(); + private static final ThreadLocal<Deque<Instance>> scopedContext = new ThreadLocal<>(); + + /** + * Returns an immutable Map containing all the key/value pairs as Renderable objects. + * @return An immutable copy of the Map at the current scope. + */ + private static Optional<Instance> getContext() { + Deque<Instance> stack = scopedContext.get(); + if (stack != null) { + return Optional.of(stack.getFirst()); + } + return Optional.empty(); + } + + /** + * Add the ScopeContext. + * @param context The ScopeContext. + */ + private static void addScopedContext(Instance context) { + Deque<Instance> stack = scopedContext.get(); + if (stack == null) { + stack = new ArrayDeque<>(); + scopedContext.set(stack); + } + stack.addFirst(context); + } + + /** + * Remove the top ScopeContext. + */ + private static void removeScopedContext() { + Deque<Instance> stack = scopedContext.get(); + if (stack != null) { + if (!stack.isEmpty()) { + stack.removeFirst(); + } + if (stack.isEmpty()) { + scopedContext.remove(); + } + } + } + /** * @hidden * Returns an unmodifiable copy of the current ScopedContext Map. This method should @@ -59,7 +102,7 @@ public class ScopedContext { * @return the Map of Renderable objects. */ public static Map<String, Renderable> getContextMap() { - Optional<Instance> context = ScopedContextDataProvider.getContext(); + Optional<Instance> context = getContext(); if (context.isPresent() && context.get().contextMap != null && !context.get().contextMap.isEmpty()) { @@ -74,7 +117,7 @@ public class ScopedContext { * @return the number of items in the context map. */ public static int size() { - Optional<Instance> context = ScopedContextDataProvider.getContext(); + Optional<Instance> context = getContext(); return context.map(instance -> instance.contextMap.size()).orElse(0); } @@ -85,7 +128,7 @@ public class ScopedContext { */ @SuppressWarnings("unchecked") public static <T> T get(String key) { - Optional<Instance> context = ScopedContextDataProvider.getContext(); + Optional<Instance> context = getContext(); if (context.isPresent()) { Renderable renderable = context.get().contextMap.get(key); if (renderable != null) { @@ -101,7 +144,7 @@ public class ScopedContext { * @return The value of the key in the current ScopedContext. */ public static String getString(String key) { - Optional<Instance> context = ScopedContextDataProvider.getContext(); + Optional<Instance> context = getContext(); if (context.isPresent()) { Renderable renderable = context.get().contextMap.get(key); if (renderable != null) { @@ -116,7 +159,7 @@ public class ScopedContext { * @param map The Map to add entries to. */ public static void addAll(Map<String, String> map) { - Optional<Instance> context = ScopedContextDataProvider.getContext(); + Optional<Instance> context = getContext(); if (context.isPresent()) { Map<String, Renderable> contextMap = context.get().contextMap; if (contextMap != null && !contextMap.isEmpty()) { @@ -136,16 +179,16 @@ public class ScopedContext { public static Instance where(String key, Object value) { if (value != null) { Renderable renderable = value instanceof Renderable ? (Renderable) value : new ObjectRenderable(value); - Instance parent = current().isPresent() ? current().get() : null; + Instance parent = getContext().isPresent() ? getContext().get() : null; return new Instance(parent, key, renderable); } else { - if (current().isPresent()) { + if (getContext().isPresent()) { Map<String, Renderable> map = getContextMap(); map.remove(key); return new Instance(map); } } - return current().isPresent() ? current().get() : new Instance(); + return getContext().isPresent() ? getContext().get() : new Instance(); } /** @@ -167,8 +210,8 @@ public class ScopedContext { public static Instance where(Map<String, ?> map) { if (map != null && !map.isEmpty()) { Map<String, Renderable> renderableMap = new HashMap<>(); - if (current().isPresent()) { - renderableMap.putAll(current().get().contextMap); + if (getContext().isPresent()) { + renderableMap.putAll(getContext().get().contextMap); } map.forEach((key, value) -> { if (value == null || (value instanceof String && ((String) value).isEmpty())) { @@ -180,7 +223,7 @@ public class ScopedContext { }); return new Instance(renderableMap); } else { - return current().isPresent() ? current().get() : new Instance(); + return getContext().isPresent() ? getContext().get() : new Instance(); } } @@ -194,15 +237,15 @@ public class ScopedContext { if (obj != null) { Renderable renderable = obj instanceof Renderable ? (Renderable) obj : new ObjectRenderable(obj); Map<String, Renderable> map = new HashMap<>(); - if (current().isPresent()) { - map.putAll(current().get().contextMap); + if (getContext().isPresent()) { + map.putAll(getContext().get().contextMap); } map.put(key, renderable); new Instance(map).run(op); } else { Map<String, Renderable> map = new HashMap<>(); - if (current().isPresent()) { - map.putAll(current().get().contextMap); + if (getContext().isPresent()) { + map.putAll(getContext().get().contextMap); } map.remove(key); new Instance(map).run(op); @@ -220,8 +263,8 @@ public class ScopedContext { if (obj != null) { Renderable renderable = obj instanceof Renderable ? (Renderable) obj : new ObjectRenderable(obj); Map<String, Renderable> map = new HashMap<>(); - if (current().isPresent()) { - map.putAll(current().get().contextMap); + if (getContext().isPresent()) { + map.putAll(getContext().get().contextMap); } map.put(key, renderable); if (executorService != null) { @@ -233,8 +276,8 @@ public class ScopedContext { } } else { Map<String, Renderable> map = new HashMap<>(); - if (current().isPresent()) { - map.putAll(current().get().contextMap); + if (getContext().isPresent()) { + map.putAll(getContext().get().contextMap); } map.remove(key); if (executorService != null) { @@ -255,8 +298,8 @@ public class ScopedContext { public static void runWhere(Map<String, ?> map, Runnable op) { if (map != null && !map.isEmpty()) { Map<String, Renderable> renderableMap = new HashMap<>(); - if (current().isPresent()) { - renderableMap.putAll(current().get().contextMap); + if (getContext().isPresent()) { + renderableMap.putAll(getContext().get().contextMap); } map.forEach((key, value) -> { renderableMap.put(key, value instanceof Renderable ? (Renderable) value : new ObjectRenderable(value)); @@ -277,15 +320,15 @@ public class ScopedContext { if (obj != null) { Renderable renderable = obj instanceof Renderable ? (Renderable) obj : new ObjectRenderable(obj); Map<String, Renderable> map = new HashMap<>(); - if (current().isPresent()) { - map.putAll(current().get().contextMap); + if (getContext().isPresent()) { + map.putAll(getContext().get().contextMap); } map.put(key, renderable); return new Instance(map).call(op); } else { Map<String, Renderable> map = new HashMap<>(); - if (current().isPresent()) { - map.putAll(current().get().contextMap); + if (getContext().isPresent()) { + map.putAll(getContext().get().contextMap); } map.remove(key); return new Instance(map).call(op); @@ -304,8 +347,8 @@ public class ScopedContext { if (obj != null) { Renderable renderable = obj instanceof Renderable ? (Renderable) obj : new ObjectRenderable(obj); Map<String, Renderable> map = new HashMap<>(); - if (current().isPresent()) { - map.putAll(current().get().contextMap); + if (getContext().isPresent()) { + map.putAll(getContext().get().contextMap); } map.put(key, renderable); if (executorService != null) { @@ -318,8 +361,8 @@ public class ScopedContext { } else { if (executorService != null) { Map<String, Renderable> map = new HashMap<>(); - if (current().isPresent()) { - map.putAll(current().get().contextMap); + if (getContext().isPresent()) { + map.putAll(getContext().get().contextMap); } map.remove(key); return executorService.submit(new Caller<R>( @@ -339,8 +382,8 @@ public class ScopedContext { public static <R> R callWhere(Map<String, ?> map, Callable<R> op) throws Exception { if (map != null && !map.isEmpty()) { Map<String, Renderable> renderableMap = new HashMap<>(); - if (current().isPresent()) { - renderableMap.putAll(current().get().contextMap); + if (getContext().isPresent()) { + renderableMap.putAll(getContext().get().contextMap); } map.forEach((key, value) -> { renderableMap.put(key, value instanceof Renderable ? (Renderable) value : new ObjectRenderable(value)); @@ -351,14 +394,6 @@ public class ScopedContext { } } - /** - * Returns an Optional holding the active ScopedContext.Instance - * @return an Optional containing the active ScopedContext, if there is one. - */ - private static Optional<Instance> current() { - return ScopedContextDataProvider.getContext(); - } - public static class Instance { private final Instance parent; @@ -500,11 +535,11 @@ public class ScopedContext { if (contextStack != null) { ThreadContext.setStack(contextStack); } - ScopedContextDataProvider.addScopedContext(scopedContext); + addScopedContext(scopedContext); try { op.run(); } finally { - ScopedContextDataProvider.removeScopedContext(); + removeScopedContext(); ThreadContext.clearAll(); } } @@ -551,11 +586,11 @@ public class ScopedContext { if (contextStack != null) { ThreadContext.setStack(contextStack); } - ScopedContextDataProvider.addScopedContext(scopedContext); + addScopedContext(scopedContext); try { return op.call(); } finally { - ScopedContextDataProvider.removeScopedContext(); + removeScopedContext(); ThreadContext.clearAll(); } } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/simple/SimpleLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/simple/SimpleLogger.java index d914f1c4c9..f5529f4258 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/simple/SimpleLogger.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/simple/SimpleLogger.java @@ -23,9 +23,10 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.ScopedContext; +import org.apache.logging.log4j.ThreadContext; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.spi.AbstractLogger; @@ -295,8 +296,8 @@ public class SimpleLogger extends AbstractLogger { } sb.append(msg.getFormattedMessage()); if (showContextMap) { - final Map<String, String> mdc = new HashMap<>(ContextData.size()); - ContextData.addAll(mdc); + final Map<String, String> mdc = new HashMap<>(ThreadContext.getImmutableContext()); + ScopedContext.getContextMap().forEach((key, value) -> mdc.put(key, value.render())); if (!mdc.isEmpty()) { sb.append(SPACE); sb.append(mdc.toString()); diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ContextDataProvider.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ContextDataProvider.java deleted file mode 100644 index d003e9c74f..0000000000 --- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ContextDataProvider.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.spi; - -import java.util.Map; -import org.apache.logging.log4j.util.StringMap; - -/** - * Source of context data to be added to each log event. - */ -public interface ContextDataProvider { - - /** - * Returns the key for a value from the context data. - * @param key the key to locate. - * @return the value or null if it is not found. - */ - default String get(String key) { - return null; - } - - /** - * Returns a Map containing context data to be injected into the event or null if no context data is to be added. - * <p> - * Thread-safety note: The returned object can safely be passed off to another thread: future changes in the - * underlying context data will not be reflected in the returned object. - * </p> - * @return A Map containing the context data or null. - */ - Map<String, String> supplyContextData(); - - /** - * Returns the number of items in this context. - * @return the number of items in the context. - */ - default int size() { - Map<String, String> contextMap = supplyContextData(); - return contextMap != null ? contextMap.size() : 0; - } - - /** - * Add all the keys in the current context to the provided Map. - * @param map the StringMap to add the keys and values to. - */ - default void addAll(Map<String, String> map) { - Map<String, String> contextMap = supplyContextData(); - if (contextMap != null) { - map.putAll(contextMap); - } - } - - /** - * Add all the keys in the current context to the provided StringMap. - * @param map the StringMap to add the keys and values to. - */ - default void addAll(StringMap map) { - Map<String, String> contextMap = supplyContextData(); - if (contextMap != null) { - contextMap.forEach(map::putValue); - } - } -} diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ScopedContextDataProvider.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ScopedContextDataProvider.java deleted file mode 100644 index f2a14c19d0..0000000000 --- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ScopedContextDataProvider.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.spi; - -import aQute.bnd.annotation.Resolution; -import aQute.bnd.annotation.spi.ServiceProvider; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.Deque; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import org.apache.logging.log4j.ScopedContext; - -/** - * ContextDataProvider for {@code Map<String, String>} data. - * @since 2.24.0 - */ -@ServiceProvider(value = ContextDataProvider.class, resolution = Resolution.OPTIONAL) -public class ScopedContextDataProvider implements ContextDataProvider { - - private static final ThreadLocal<Deque<ScopedContext.Instance>> scopedContext = new ThreadLocal<>(); - - /** - * Returns an immutable Map containing all the key/value pairs as Renderable objects. - * @return An immutable copy of the Map at the current scope. - */ - public static Optional<ScopedContext.Instance> getContext() { - Deque<ScopedContext.Instance> stack = scopedContext.get(); - if (stack != null) { - return Optional.of(stack.getFirst()); - } - return Optional.empty(); - } - - /** - * Add the ScopeContext. - * @param context The ScopeContext. - */ - public static void addScopedContext(ScopedContext.Instance context) { - Deque<ScopedContext.Instance> stack = scopedContext.get(); - if (stack == null) { - stack = new ArrayDeque<>(); - scopedContext.set(stack); - } - stack.addFirst(context); - } - - /** - * Remove the top ScopeContext. - */ - public static void removeScopedContext() { - Deque<ScopedContext.Instance> stack = scopedContext.get(); - if (stack != null) { - if (!stack.isEmpty()) { - stack.removeFirst(); - } - if (stack.isEmpty()) { - scopedContext.remove(); - } - } - } - - @Override - public String get(String key) { - return ScopedContext.getString(key); - } - - @Override - public Map<String, String> supplyContextData() { - Map<String, ScopedContext.Renderable> contextMap = ScopedContext.getContextMap(); - if (!contextMap.isEmpty()) { - Map<String, String> map = new HashMap<>(); - contextMap.forEach((key, value) -> map.put(key, value.render())); - return map; - } else { - return Collections.emptyMap(); - } - } - - @Override - public int size() { - return ScopedContext.size(); - } - - @Override - public void addAll(Map<String, String> map) { - ScopedContext.addAll(map); - } -} diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java index 5bb479f66c..f8b5b11402 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java @@ -19,7 +19,6 @@ package org.apache.logging.log4j.core.async; import com.lmax.disruptor.EventTranslatorVararg; import com.lmax.disruptor.dsl.Disruptor; import java.util.List; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.ThreadContext; @@ -31,6 +30,7 @@ import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.LoggerConfig; import org.apache.logging.log4j.core.config.Property; import org.apache.logging.log4j.core.config.ReliabilityStrategy; +import org.apache.logging.log4j.core.impl.ContextData; import org.apache.logging.log4j.core.impl.ContextDataFactory; import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory; import org.apache.logging.log4j.core.util.Clock; diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java index c965ce974d..ef79ca5b3e 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java @@ -17,11 +17,11 @@ package org.apache.logging.log4j.core.async; import com.lmax.disruptor.EventTranslator; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.ThreadContext.ContextStack; import org.apache.logging.log4j.core.ContextDataInjector; +import org.apache.logging.log4j.core.impl.ContextData; import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory; import org.apache.logging.log4j.core.util.Clock; import org.apache.logging.log4j.core.util.NanoClock; diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java index d2de85fe4d..b1f3c8f0d2 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java @@ -19,7 +19,6 @@ package org.apache.logging.log4j.core.filter; import java.util.HashMap; import java.util.Map; import java.util.Objects; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.ThreadContext; @@ -32,11 +31,12 @@ 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.impl.ContextData; import org.apache.logging.log4j.core.impl.ContextDataFactory; import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory; +import org.apache.logging.log4j.core.util.ContextDataProvider; import org.apache.logging.log4j.core.util.KeyValuePair; import org.apache.logging.log4j.message.Message; -import org.apache.logging.log4j.spi.ContextDataProvider; import org.apache.logging.log4j.util.PerformanceSensitive; import org.apache.logging.log4j.util.StringMap; diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java index 7b27f88450..5116876555 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.core.Filter; @@ -33,6 +32,7 @@ import org.apache.logging.log4j.core.config.plugins.PluginAliases; 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.impl.ContextData; import org.apache.logging.log4j.core.util.KeyValuePair; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.util.IndexedReadOnlyStringMap; diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/ContextData.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextData.java similarity index 96% rename from log4j-api/src/main/java/org/apache/logging/log4j/ContextData.java rename to log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextData.java index 1b9445dcd8..df951a2e9f 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/ContextData.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextData.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.logging.log4j; +package org.apache.logging.log4j.core.impl; import java.util.ArrayList; import java.util.Collection; @@ -24,7 +24,8 @@ import java.util.Map; import java.util.ServiceLoader; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.logging.log4j.spi.ContextDataProvider; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.util.ContextDataProvider; import org.apache.logging.log4j.status.StatusLogger; import org.apache.logging.log4j.util.ServiceLoaderUtil; import org.apache.logging.log4j.util.StringMap; diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java index bc02b085bb..aff4d5893c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java @@ -24,7 +24,6 @@ import java.rmi.MarshalledObject; import java.util.List; import java.util.Map; import java.util.Objects; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.ThreadContext; diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java index 5a916d4003..5b41469aac 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java @@ -17,7 +17,6 @@ package org.apache.logging.log4j.core.impl; import java.util.List; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.ThreadContext; diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextDataProvider.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ScopedContextDataProvider.java similarity index 60% rename from log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextDataProvider.java rename to log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ScopedContextDataProvider.java index d6e28f00d8..805c0979e7 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextDataProvider.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ScopedContextDataProvider.java @@ -14,36 +14,47 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.logging.log4j.spi; +package org.apache.logging.log4j.core.impl; import aQute.bnd.annotation.Resolution; import aQute.bnd.annotation.spi.ServiceProvider; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; -import org.apache.logging.log4j.ThreadContext; +import org.apache.logging.log4j.ScopedContext; +import org.apache.logging.log4j.core.util.ContextDataProvider; /** - * ContextDataProvider for ThreadContext data. + * ContextDataProvider for {@code Map<String, String>} data. + * @since 2.24.0 */ @ServiceProvider(value = ContextDataProvider.class, resolution = Resolution.OPTIONAL) -public class ThreadContextDataProvider implements ContextDataProvider { +public class ScopedContextDataProvider implements ContextDataProvider { @Override public String get(String key) { - return ThreadContext.get(key); + return ScopedContext.getString(key); } @Override public Map<String, String> supplyContextData() { - return ThreadContext.getImmutableContext(); + Map<String, ScopedContext.Renderable> contextMap = ScopedContext.getContextMap(); + if (!contextMap.isEmpty()) { + Map<String, String> map = new HashMap<>(); + contextMap.forEach((key, value) -> map.put(key, value.render())); + return map; + } else { + return Collections.emptyMap(); + } } @Override public int size() { - return ThreadContext.getContext().size(); + return ScopedContext.size(); } @Override public void addAll(Map<String, String> map) { - map.putAll(ThreadContext.getContext()); + ScopedContext.addAll(map); } } 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 0362984c5b..06b9bcd084 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 @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.ThreadContext; import org.apache.logging.log4j.core.ContextDataInjector; @@ -236,9 +235,9 @@ public class ThreadContextDataInjector { private static class ProviderIterator implements Iterator<ContextDataProvider> { - private final Iterator<org.apache.logging.log4j.spi.ContextDataProvider> iter; + private final Iterator<ContextDataProvider> iter; - public ProviderIterator(Iterator<org.apache.logging.log4j.spi.ContextDataProvider> iter) { + public ProviderIterator(Iterator<ContextDataProvider> iter) { this.iter = iter; } @@ -249,7 +248,7 @@ public class ThreadContextDataInjector { @Override public ContextDataProvider next() { - org.apache.logging.log4j.spi.ContextDataProvider next = iter.next(); + ContextDataProvider next = iter.next(); if (next instanceof ContextDataProvider) { return (ContextDataProvider) next; } else if (next != null) { @@ -261,9 +260,9 @@ public class ThreadContextDataInjector { private static class ProviderWrapper implements ContextDataProvider { - private final org.apache.logging.log4j.spi.ContextDataProvider provider; + private final ContextDataProvider provider; - public ProviderWrapper(org.apache.logging.log4j.spi.ContextDataProvider provider) { + public ProviderWrapper(ContextDataProvider provider) { this.provider = provider; } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataProvider.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataProvider.java index a20216c755..949f8868a4 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataProvider.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataProvider.java @@ -29,6 +29,11 @@ import org.apache.logging.log4j.util.StringMap; @ServiceProvider(value = ContextDataProvider.class, resolution = Resolution.OPTIONAL) public class ThreadContextDataProvider implements ContextDataProvider { + @Override + public String get(String key) { + return ThreadContext.get(key); + } + @Override public Map<String, String> supplyContextData() { return ThreadContext.getImmutableContext(); @@ -38,4 +43,14 @@ public class ThreadContextDataProvider implements ContextDataProvider { public StringMap supplyStringMap() { return ThreadContext.getThreadContextMap().getReadOnlyContextData(); } + + @Override + public int size() { + return ThreadContext.getContext().size(); + } + + @Override + public void addAll(Map<String, String> map) { + map.putAll(ThreadContext.getContext()); + } } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/ContextMapLookup.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/ContextMapLookup.java index b24f1203a8..9b841bb396 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/ContextMapLookup.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/ContextMapLookup.java @@ -16,12 +16,12 @@ */ package org.apache.logging.log4j.core.lookup; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.ScopedContext; import org.apache.logging.log4j.ThreadContext; import org.apache.logging.log4j.core.ContextDataInjector; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.impl.ContextData; import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory; /** diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/osgi/Activator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/osgi/Activator.java index 17bde215ff..5f6f1da67c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/osgi/Activator.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/osgi/Activator.java @@ -18,14 +18,14 @@ package org.apache.logging.log4j.core.osgi; import java.util.Collection; import java.util.concurrent.atomic.AtomicReference; -import org.apache.logging.log4j.ContextData; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.config.plugins.util.PluginRegistry; +import org.apache.logging.log4j.core.impl.ContextData; import org.apache.logging.log4j.core.impl.Log4jProvider; +import org.apache.logging.log4j.core.impl.ThreadContextDataProvider; import org.apache.logging.log4j.core.util.Constants; -import org.apache.logging.log4j.spi.ContextDataProvider; -import org.apache.logging.log4j.spi.ThreadContextDataProvider; +import org.apache.logging.log4j.core.util.ContextDataProvider; import org.apache.logging.log4j.status.StatusLogger; import org.apache.logging.log4j.util.PropertiesUtil; import org.apache.logging.log4j.util.ProviderActivator; diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/ContextDataProvider.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/ContextDataProvider.java index 086ac93981..6eeeeef9b5 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/ContextDataProvider.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/ContextDataProvider.java @@ -22,11 +22,26 @@ import org.apache.logging.log4j.util.StringMap; /** * Source of context data to be added to each log event. - * @deprecated Use ContextDataProvider from Log4j API from 2.24.0. */ -@Deprecated -public interface ContextDataProvider extends org.apache.logging.log4j.spi.ContextDataProvider { +public interface ContextDataProvider { + /** + * Returns the key for a value from the context data. + * @param key the key to locate. + * @return the value or null if it is not found. + */ + default String get(String key) { + return null; + } + + /** + * Returns a Map containing context data to be injected into the event or null if no context data is to be added. + * <p> + * Thread-safety note: The returned object can safely be passed off to another thread: future changes in the + * underlying context data will not be reflected in the returned object. + * </p> + * @return A Map containing the context data or null. + */ Map<String, String> supplyContextData(); /** @@ -42,4 +57,35 @@ public interface ContextDataProvider extends org.apache.logging.log4j.spi.Contex default StringMap supplyStringMap() { return new JdkMapAdapterStringMap(supplyContextData(), true); } + + /** + * Returns the number of items in this context. + * @return the number of items in the context. + */ + default int size() { + Map<String, String> contextMap = supplyContextData(); + return contextMap != null ? contextMap.size() : 0; + } + + /** + * Add all the keys in the current context to the provided Map. + * @param map the StringMap to add the keys and values to. + */ + default void addAll(Map<String, String> map) { + Map<String, String> contextMap = supplyContextData(); + if (contextMap != null) { + map.putAll(contextMap); + } + } + + /** + * Add all the keys in the current context to the provided StringMap. + * @param map the StringMap to add the keys and values to. + */ + default void addAll(StringMap map) { + Map<String, String> contextMap = supplyContextData(); + if (contextMap != null) { + contextMap.forEach(map::putValue); + } + } }
