Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for custom context data in ctx lookup #2846

Merged
merged 1 commit into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,19 @@ public interface ContextDataInjector {
* the implementation of this method. It is not safe to pass the returned object to another thread.
* </p>
* @return a {@code ReadOnlyStringMap} object reflecting the current state of the context, may not return {@code null}
* @deprecated Since 2.24.0 use {@link #getValue} instead.
*/
@Deprecated
ReadOnlyStringMap rawContextData();

/**
* Retrieves a single context data value.
*
* @param key The context data key of the value to retrieve.
* @return A context data value.
* @since 2.24.0
*/
default Object getValue(final String key) {
return rawContextData().getValue(key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import org.apache.logging.log4j.core.util.KeyValuePair;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.util.PerformanceSensitive;
import org.apache.logging.log4j.util.ReadOnlyStringMap;
import org.apache.logging.log4j.util.StringMap;

/**
Expand Down Expand Up @@ -125,10 +124,9 @@ public boolean equals(final Object obj) {
return true;
}

private Result filter(final Level level, final ReadOnlyStringMap contextMap) {
final String value = contextMap.getValue(key);
private Result filter(final Level level, final Object value) {
if (value != null) {
Level ctxLevel = levelMap.get(value);
Level ctxLevel = levelMap.get(Objects.toString(value, null));
if (ctxLevel == null) {
ctxLevel = defaultThreshold;
}
Expand All @@ -139,35 +137,31 @@ private Result filter(final Level level, final ReadOnlyStringMap contextMap) {

@Override
public Result filter(final LogEvent event) {
return filter(event.getLevel(), event.getContextData());
return filter(event.getLevel(), event.getContextData().getValue(key));
}

@Override
public Result filter(
final Logger logger, final Level level, final Marker marker, final Message msg, final Throwable t) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
public Result filter(
final Logger logger, final Level level, final Marker marker, final Object msg, final Throwable t) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
public Result filter(
final Logger logger, final Level level, final Marker marker, final String msg, final Object... params) {
return filter(level, currentContextData());
}

private ReadOnlyStringMap currentContextData() {
return injector.rawContextData();
return filter(level, injector.getValue(key));
}

@Override
public Result filter(
final Logger logger, final Level level, final Marker marker, final String msg, final Object p0) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
Expand All @@ -178,7 +172,7 @@ public Result filter(
final String msg,
final Object p0,
final Object p1) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
Expand All @@ -190,7 +184,7 @@ public Result filter(
final Object p0,
final Object p1,
final Object p2) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
Expand All @@ -203,7 +197,7 @@ public Result filter(
final Object p1,
final Object p2,
final Object p3) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
Expand All @@ -217,7 +211,7 @@ public Result filter(
final Object p2,
final Object p3,
final Object p4) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
Expand All @@ -232,7 +226,7 @@ public Result filter(
final Object p3,
final Object p4,
final Object p5) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
Expand All @@ -248,7 +242,7 @@ public Result filter(
final Object p4,
final Object p5,
final Object p6) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
Expand All @@ -265,7 +259,7 @@ public Result filter(
final Object p5,
final Object p6,
final Object p7) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
Expand All @@ -283,7 +277,7 @@ public Result filter(
final Object p6,
final Object p7,
final Object p8) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

@Override
Expand All @@ -302,7 +296,7 @@ public Result filter(
final Object p7,
final Object p8,
final Object p9) {
return filter(level, currentContextData());
return filter(level, injector.getValue(key));
}

public String getKey() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.ContextDataInjector;
Expand All @@ -39,7 +40,6 @@
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
import org.apache.logging.log4j.util.PerformanceSensitive;
import org.apache.logging.log4j.util.ReadOnlyStringMap;
import org.apache.logging.log4j.util.StringMap;

/**
Expand Down Expand Up @@ -109,26 +109,22 @@ public Result filter(
private Result filter() {
boolean match = false;
if (useMap) {
ReadOnlyStringMap currentContextData = null;
final IndexedReadOnlyStringMap map = getStringMap();
for (int i = 0; i < map.size(); i++) {
if (currentContextData == null) {
currentContextData = currentContextData();
}
final String toMatch = currentContextData.getValue(map.getKeyAt(i));
match = toMatch != null && ((List<String>) map.getValueAt(i)).contains(toMatch);
final String toMatch = getContextValue(map.getKeyAt(i));
match = toMatch != null && map.<List<String>>getValueAt(i).contains(toMatch);
if ((!isAnd() && match) || (isAnd() && !match)) {
break;
}
}
} else {
match = value.equals(currentContextData().getValue(key));
match = value.equals(getContextValue(key));
}
return match ? onMatch : onMismatch;
}

private ReadOnlyStringMap currentContextData() {
return injector.rawContextData();
private String getContextValue(final String key) {
return Objects.toString(injector.getValue(key), null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,33 @@ private static List<ContextDataProvider> getServiceProviders() {
return Collections.unmodifiableList(providers);
}

private abstract static class AbstractContextDataInjector implements ContextDataInjector {

final List<ContextDataProvider> providers;

AbstractContextDataInjector() {
this.providers = getProviders();
}

@Override
public Object getValue(String key) {
for (final ContextDataProvider provider : providers) {
final Object value = provider.getValue(key);
if (value != null) {
return value;
}
}
return null;
}
}

/**
* Default {@code ContextDataInjector} for the legacy {@code Map<String, String>}-based ThreadContext (which is
* also the ThreadContext implementation used for web applications).
* <p>
* This injector always puts key-value pairs into the specified reusable StringMap.
*/
public static class ForDefaultThreadContextMap implements ContextDataInjector {

private final List<ContextDataProvider> providers;

public ForDefaultThreadContextMap() {
providers = getProviders();
}
public static class ForDefaultThreadContextMap extends AbstractContextDataInjector {

/**
* Puts key-value pairs from both the specified list of properties as well as the thread context into the
Expand Down Expand Up @@ -171,12 +185,7 @@ public ReadOnlyStringMap rawContextData() {
* <p>
* This injector always puts key-value pairs into the specified reusable StringMap.
*/
public static class ForGarbageFreeThreadContextMap implements ContextDataInjector {
private final List<ContextDataProvider> providers;

public ForGarbageFreeThreadContextMap() {
this.providers = getProviders();
}
public static class ForGarbageFreeThreadContextMap extends AbstractContextDataInjector {

/**
* Puts key-value pairs from both the specified list of properties as well as the thread context into the
Expand Down Expand Up @@ -212,12 +221,8 @@ public ReadOnlyStringMap rawContextData() {
* structure. Otherwise the configuration properties are combined with the thread context key-value pairs into the
* specified reusable StringMap.
*/
public static class ForCopyOnWriteThreadContextMap implements ContextDataInjector {
private final List<ContextDataProvider> providers;
public static class ForCopyOnWriteThreadContextMap extends AbstractContextDataInjector {

public ForCopyOnWriteThreadContextMap() {
this.providers = getProviders();
}
/**
* If there are no configuration properties, this injector will return the thread context's internal data
* structure. Otherwise the configuration properties are combined with the thread context key-value pairs into the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* Log4j 2 private implementation classes.
*/
@Export
@Version("2.23.0")
@Version("2.24.0")
package org.apache.logging.log4j.core.impl;

import org.osgi.annotation.bundle.Export;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
*/
package org.apache.logging.log4j.core.lookup;

import java.util.Objects;
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.ContextDataInjectorFactory;
import org.apache.logging.log4j.util.ReadOnlyStringMap;

/**
* Looks up keys from the context. By default this is the {@link ThreadContext}, but users may
Expand All @@ -40,11 +40,7 @@ public class ContextMapLookup implements StrLookup {
*/
@Override
public String lookup(final String key) {
return currentContextData().getValue(key);
}

private ReadOnlyStringMap currentContextData() {
return injector.rawContextData();
return Objects.toString(injector.getValue(key), null);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,17 @@ public interface ContextDataProvider {
default StringMap supplyStringMap() {
return new JdkMapAdapterStringMap(supplyContextData(), true);
}

/**
* Retrieves a single context data value.
* <p>
* This method avoids the overhead of copying the entire context data, when only a single value is needed.
* </p>
* @param key The context data key of the value to retrieve.
* @return A context data value.
* @since 2.24.0
*/
default Object getValue(final String key) {
return supplyContextData().get(key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* Log4j 2 helper classes.
*/
@Export
@Version("2.20.2")
@Version("2.24.0")
package org.apache.logging.log4j.core.util;

import org.osgi.annotation.bundle.Export;
Expand Down
8 changes: 8 additions & 0 deletions src/changelog/.2.x.x/2331_custom_context_data_in_lookup.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://logging.apache.org/xml/ns"
xsi:schemaLocation="https://logging.apache.org/xml/ns https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
type="fixed">
<issue id="2331" link="https://github.com/apache/logging-log4j2/issues/2331"/>
<description format="asciidoc">Fix custom thread-context data provider handling in lookups and filters.</description>
</entry>
Loading