parent
5ca904c17a
commit
634933b3e5
|
@ -149,7 +149,7 @@ class JsonValueWriter {
|
|||
}
|
||||
}
|
||||
|
||||
private <V> boolean canWriteAsArray(Iterable<?> iterable) {
|
||||
private boolean canWriteAsArray(Iterable<?> iterable) {
|
||||
return !(iterable instanceof Path);
|
||||
}
|
||||
|
||||
|
@ -349,7 +349,8 @@ class JsonValueWriter {
|
|||
// Lambda isn't detected with the correct nullability
|
||||
@SuppressWarnings({ "unchecked", "NullAway" })
|
||||
private <V> @Nullable V processValue(@Nullable V value, ValueProcessor<?> valueProcessor) {
|
||||
return (V) LambdaSafe.callback(ValueProcessor.class, valueProcessor, this.path, new Object[] { value })
|
||||
return (V) LambdaSafe
|
||||
.callback(ValueProcessor.class, valueProcessor, this.path, new @Nullable Object[] { value })
|
||||
.invokeAnd((call) -> call.processValue(this.path, value))
|
||||
.get(value);
|
||||
}
|
||||
|
@ -389,7 +390,7 @@ class JsonValueWriter {
|
|||
|
||||
private int index;
|
||||
|
||||
private Set<String> names = new HashSet<>();
|
||||
private final Set<String> names = new HashSet<>();
|
||||
|
||||
private ActiveSeries(Series series) {
|
||||
this.series = series;
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.function.Predicate;
|
|||
import java.util.function.Supplier;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.json.JsonValueWriter.Series;
|
||||
|
@ -118,9 +119,9 @@ public interface JsonWriter<T> {
|
|||
* Return a new {@link JsonWriter} instance that appends the given suffix after the
|
||||
* JSON has been written.
|
||||
* @param suffix the suffix to write, if any
|
||||
* @return a new {@link JsonWriter} instance that appends a suffixafter the JSON
|
||||
* @return a new {@link JsonWriter} instance that appends a suffix after the JSON
|
||||
*/
|
||||
default JsonWriter<T> withSuffix(String suffix) {
|
||||
default JsonWriter<T> withSuffix(@Nullable String suffix) {
|
||||
if (!StringUtils.hasLength(suffix)) {
|
||||
return this;
|
||||
}
|
||||
|
@ -221,7 +222,7 @@ public interface JsonWriter<T> {
|
|||
* @param supplier a supplier of the value
|
||||
* @return the added {@link Member} which may be configured further
|
||||
*/
|
||||
public <V> Member<V> add(String name, Supplier<V> supplier) {
|
||||
public <V> Member<V> add(String name, Supplier<@Nullable V> supplier) {
|
||||
Assert.notNull(supplier, "'supplier' must not be null");
|
||||
return add(name, (instance) -> supplier.get());
|
||||
}
|
||||
|
@ -233,7 +234,7 @@ public interface JsonWriter<T> {
|
|||
* @param extractor {@link Extractor} to extract the value
|
||||
* @return the added {@link Member} which may be configured further
|
||||
*/
|
||||
public <V> Member<V> add(String name, Extractor<T, ? extends @Nullable V> extractor) {
|
||||
public <V> Member<V> add(String name, Extractor<T, V> extractor) {
|
||||
Assert.notNull(name, "'name' must not be null");
|
||||
Assert.notNull(extractor, "'extractor' must not be null");
|
||||
return addMember(name, extractor);
|
||||
|
@ -268,7 +269,7 @@ public interface JsonWriter<T> {
|
|||
* @param value the member value
|
||||
* @return the added {@link Member} which may be configured further
|
||||
*/
|
||||
public <V> Member<V> from(V value) {
|
||||
public <V> Member<V> from(@Nullable V value) {
|
||||
return from((instance) -> value);
|
||||
}
|
||||
|
||||
|
@ -279,7 +280,7 @@ public interface JsonWriter<T> {
|
|||
* @param supplier a supplier of the value
|
||||
* @return the added {@link Member} which may be configured further
|
||||
*/
|
||||
public <V> Member<V> from(Supplier<V> supplier) {
|
||||
public <V> Member<V> from(Supplier<@Nullable V> supplier) {
|
||||
Assert.notNull(supplier, "'supplier' must not be null");
|
||||
return from((instance) -> supplier.get());
|
||||
}
|
||||
|
@ -323,7 +324,7 @@ public interface JsonWriter<T> {
|
|||
this.jsonProcessors.valueProcessors().add(valueProcessor);
|
||||
}
|
||||
|
||||
private <V> Member<V> addMember(@Nullable String name, Extractor<T, ? extends @Nullable V> extractor) {
|
||||
private <V> Member<V> addMember(@Nullable String name, Extractor<T, V> extractor) {
|
||||
Member<V> member = new Member<>(this.members.size(), name, ValueExtractor.of(extractor));
|
||||
this.members.add(member);
|
||||
return member;
|
||||
|
@ -396,7 +397,7 @@ public interface JsonWriter<T> {
|
|||
* @param extractor an function used to extract the value to test
|
||||
* @return a {@link Member} which may be configured further
|
||||
*/
|
||||
public Member<T> whenNotNull(Function<T, ?> extractor) {
|
||||
public Member<T> whenNotNull(Function<@Nullable T, ?> extractor) {
|
||||
Assert.notNull(extractor, "'extractor' must not be null");
|
||||
return when((instance) -> Objects.nonNull(extractor.apply(instance)));
|
||||
}
|
||||
|
@ -417,7 +418,8 @@ public interface JsonWriter<T> {
|
|||
* @return a {@link Member} which may be configured further
|
||||
*/
|
||||
public Member<T> whenNotEmpty() {
|
||||
return whenNot(ObjectUtils::isEmpty);
|
||||
Predicate<@Nullable T> isEmpty = ObjectUtils::isEmpty;
|
||||
return whenNot(isEmpty);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -425,7 +427,7 @@ public interface JsonWriter<T> {
|
|||
* @param predicate the predicate to test
|
||||
* @return a {@link Member} which may be configured further
|
||||
*/
|
||||
public Member<T> whenNot(Predicate<T> predicate) {
|
||||
public Member<T> whenNot(Predicate<@Nullable T> predicate) {
|
||||
Assert.notNull(predicate, "'predicate' must not be null");
|
||||
return when(predicate.negate());
|
||||
}
|
||||
|
@ -448,7 +450,7 @@ public interface JsonWriter<T> {
|
|||
* @return a {@link Member} which may be configured further
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> Member<R> as(Extractor<T, ? extends @Nullable R> extractor) {
|
||||
public <R> Member<R> as(Extractor<T, R> extractor) {
|
||||
Assert.notNull(extractor, "'adapter' must not be null");
|
||||
Member<R> result = (Member<R>) this;
|
||||
result.valueExtractor = this.valueExtractor.as(extractor::extract);
|
||||
|
@ -688,7 +690,7 @@ public interface JsonWriter<T> {
|
|||
* @param <T> the member type
|
||||
*/
|
||||
@FunctionalInterface
|
||||
interface ValueExtractor<T> {
|
||||
interface ValueExtractor<T extends @Nullable Object> {
|
||||
|
||||
/**
|
||||
* Represents a skipped value.
|
||||
|
@ -722,7 +724,7 @@ public interface JsonWriter<T> {
|
|||
* @param extractor the extractor to use
|
||||
* @return a new {@link ValueExtractor}
|
||||
*/
|
||||
default <R> ValueExtractor<R> as(Extractor<T, ? extends @Nullable R> extractor) {
|
||||
default <R> ValueExtractor<R> as(Extractor<T, R> extractor) {
|
||||
return (instance) -> apply(extract(instance), extractor);
|
||||
}
|
||||
|
||||
|
@ -946,7 +948,7 @@ public interface JsonWriter<T> {
|
|||
* @param existingName the existing and possibly already processed name.
|
||||
* @return the new name
|
||||
*/
|
||||
String processName(MemberPath path, String existingName);
|
||||
@Nullable String processName(MemberPath path, String existingName);
|
||||
|
||||
/**
|
||||
* Factory method to create a new {@link NameProcessor} for the given operation.
|
||||
|
@ -969,7 +971,7 @@ public interface JsonWriter<T> {
|
|||
* @param <T> the value type
|
||||
*/
|
||||
@FunctionalInterface
|
||||
interface ValueProcessor<T> {
|
||||
interface ValueProcessor<T extends @Nullable Object> {
|
||||
|
||||
/**
|
||||
* Process the value at the given path.
|
||||
|
@ -977,7 +979,7 @@ public interface JsonWriter<T> {
|
|||
* @param value the value being written (may be {@code null})
|
||||
* @return the processed value
|
||||
*/
|
||||
T processValue(MemberPath path, T value);
|
||||
@Nullable T processValue(MemberPath path, @Nullable T value);
|
||||
|
||||
/**
|
||||
* Return a new processor from this one that only applied to members with the
|
||||
|
@ -1018,7 +1020,8 @@ public interface JsonWriter<T> {
|
|||
* type.
|
||||
*/
|
||||
default ValueProcessor<T> whenInstanceOf(Class<?> type) {
|
||||
return when(type::isInstance);
|
||||
Predicate<@Nullable T> isInstance = type::isInstance;
|
||||
return when(isInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1028,7 +1031,7 @@ public interface JsonWriter<T> {
|
|||
* @return a new {@link ValueProcessor} that only applies when the predicate
|
||||
* matches
|
||||
*/
|
||||
default ValueProcessor<T> when(Predicate<T> predicate) {
|
||||
default ValueProcessor<T> when(Predicate<@Nullable T> predicate) {
|
||||
return (name, value) -> (predicate.test(value)) ? processValue(name, value) : value;
|
||||
}
|
||||
|
||||
|
@ -1040,7 +1043,7 @@ public interface JsonWriter<T> {
|
|||
* @param action the action to apply
|
||||
* @return a new {@link ValueProcessor} instance
|
||||
*/
|
||||
static <T> ValueProcessor<T> of(Class<? extends T> type, UnaryOperator<T> action) {
|
||||
static <T> ValueProcessor<T> of(Class<? extends T> type, UnaryOperator<@Nullable T> action) {
|
||||
return of(action).whenInstanceOf(type);
|
||||
}
|
||||
|
||||
|
@ -1051,7 +1054,7 @@ public interface JsonWriter<T> {
|
|||
* @param action the action to apply
|
||||
* @return a new {@link ValueProcessor} instance
|
||||
*/
|
||||
static <T> ValueProcessor<T> of(UnaryOperator<T> action) {
|
||||
static <T> ValueProcessor<T> of(UnaryOperator<@Nullable T> action) {
|
||||
Assert.notNull(action, "'action' must not be null");
|
||||
return (name, value) -> action.apply(value);
|
||||
}
|
||||
|
@ -1065,14 +1068,14 @@ public interface JsonWriter<T> {
|
|||
* @param <R> the result type
|
||||
*/
|
||||
@FunctionalInterface
|
||||
interface Extractor<T, R> {
|
||||
interface Extractor<T extends @Nullable Object, R extends @Nullable Object> {
|
||||
|
||||
/**
|
||||
* Extract from the given value.
|
||||
* @param value the source value (never {@code null})
|
||||
* @return an extracted value or {@code null}
|
||||
*/
|
||||
@Nullable R extract(T value);
|
||||
@Nullable R extract(@NonNull T value);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@ package org.springframework.boot.logging.log4j2;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Set;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -37,6 +38,7 @@ import org.springframework.boot.json.WritableJson;
|
|||
import org.springframework.boot.logging.StackTracePrinter;
|
||||
import org.springframework.boot.logging.structured.CommonStructuredLogFormat;
|
||||
import org.springframework.boot.logging.structured.ContextPairs;
|
||||
import org.springframework.boot.logging.structured.ContextPairs.Joiner;
|
||||
import org.springframework.boot.logging.structured.GraylogExtendedLogFormatProperties;
|
||||
import org.springframework.boot.logging.structured.JsonWriterStructuredLogFormatter;
|
||||
import org.springframework.boot.logging.structured.StructuredLogFormatter;
|
||||
|
@ -91,12 +93,15 @@ class GraylogExtendedLogFormatStructuredLogFormatter extends JsonWriterStructure
|
|||
members.add("_process_thread_name", LogEvent::getThreadName);
|
||||
GraylogExtendedLogFormatProperties.get(environment).jsonMembers(members);
|
||||
members.add("_log_logger", LogEvent::getLoggerName);
|
||||
Predicate<@Nullable ReadOnlyStringMap> mapIsEmpty = (map) -> map == null || map.isEmpty();
|
||||
members.from(LogEvent::getContextData)
|
||||
.whenNot(ReadOnlyStringMap::isEmpty)
|
||||
.whenNot(mapIsEmpty)
|
||||
.usingPairs(contextPairs.flat(additionalFieldJoiner(),
|
||||
GraylogExtendedLogFormatStructuredLogFormatter::addContextDataPairs));
|
||||
Function<@Nullable LogEvent, @Nullable Object> getThrownProxy = (event) -> (event != null)
|
||||
? event.getThrownProxy() : null;
|
||||
members.add()
|
||||
.whenNotNull(LogEvent::getThrownProxy)
|
||||
.whenNotNull(getThrownProxy)
|
||||
.usingMembers((thrownProxyMembers) -> throwableMembers(thrownProxyMembers, extractor));
|
||||
}
|
||||
|
||||
|
@ -140,7 +145,7 @@ class GraylogExtendedLogFormatStructuredLogFormatter extends JsonWriterStructure
|
|||
contextPairs.add((contextData, pairs) -> contextData.forEach(pairs::accept));
|
||||
}
|
||||
|
||||
private static BinaryOperator<@Nullable String> additionalFieldJoiner() {
|
||||
private static Joiner additionalFieldJoiner() {
|
||||
return (prefix, name) -> {
|
||||
name = prefix + name;
|
||||
if (!FIELD_NAME_VALID_PATTERN.matcher(name).matches()) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.time.ZoneId;
|
|||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
|
@ -61,13 +62,15 @@ class LogstashStructuredLogFormatter extends JsonWriterStructuredLogFormatter<Lo
|
|||
members.add("thread_name", LogEvent::getThreadName);
|
||||
members.add("level", LogEvent::getLevel).as(Level::name);
|
||||
members.add("level_value", LogEvent::getLevel).as(Level::intLevel);
|
||||
Predicate<@Nullable ReadOnlyStringMap> mapIsEmpty = (map) -> map == null || map.isEmpty();
|
||||
members.from(LogEvent::getContextData)
|
||||
.whenNot(ReadOnlyStringMap::isEmpty)
|
||||
.whenNot(mapIsEmpty)
|
||||
.usingPairs(contextPairs.flat("_", LogstashStructuredLogFormatter::addContextDataPairs));
|
||||
Predicate<@Nullable Set<String>> collectionIsEmpty = CollectionUtils::isEmpty;
|
||||
members.add("tags", LogEvent::getMarker)
|
||||
.whenNotNull()
|
||||
.as(LogstashStructuredLogFormatter::getMarkers)
|
||||
.whenNot(CollectionUtils::isEmpty);
|
||||
.whenNot(collectionIsEmpty);
|
||||
members.add("stack_trace", LogEvent::getThrownProxy).whenNotNull().as(extractor::stackTrace);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
|
@ -77,7 +78,9 @@ class ElasticCommonSchemaStructuredLogFormatter extends JsonWriterStructuredLogF
|
|||
pairs.addMapEntries(ILoggingEvent::getMDCPropertyMap);
|
||||
pairs.add(ILoggingEvent::getKeyValuePairs, keyValuePairExtractor);
|
||||
}));
|
||||
members.add().whenNotNull(ILoggingEvent::getThrowableProxy).usingMembers((throwableMembers) -> {
|
||||
Function<@Nullable ILoggingEvent, @Nullable Object> getThrowableProxy = (event) -> (event != null)
|
||||
? event.getThrowableProxy() : null;
|
||||
members.add().whenNotNull(getThrowableProxy).usingMembers((throwableMembers) -> {
|
||||
throwableMembers.add("error").usingMembers((error) -> {
|
||||
error.add("type", ILoggingEvent::getThrowableProxy).as(IThrowableProxy::getClassName);
|
||||
error.add("message", ILoggingEvent::getThrowableProxy).as(IThrowableProxy::getMessage);
|
||||
|
|
|
@ -18,7 +18,7 @@ package org.springframework.boot.logging.logback;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Set;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
|
||||
|
@ -37,6 +37,7 @@ import org.springframework.boot.json.WritableJson;
|
|||
import org.springframework.boot.logging.StackTracePrinter;
|
||||
import org.springframework.boot.logging.structured.CommonStructuredLogFormat;
|
||||
import org.springframework.boot.logging.structured.ContextPairs;
|
||||
import org.springframework.boot.logging.structured.ContextPairs.Joiner;
|
||||
import org.springframework.boot.logging.structured.GraylogExtendedLogFormatProperties;
|
||||
import org.springframework.boot.logging.structured.JsonWriterStructuredLogFormatter;
|
||||
import org.springframework.boot.logging.structured.StructuredLogFormatter;
|
||||
|
@ -100,8 +101,10 @@ class GraylogExtendedLogFormatStructuredLogFormatter extends JsonWriterStructure
|
|||
pairs.addMapEntries(ILoggingEvent::getMDCPropertyMap);
|
||||
pairs.add(ILoggingEvent::getKeyValuePairs, keyValuePairExtractor);
|
||||
}));
|
||||
Function<@Nullable ILoggingEvent, @Nullable Object> getThrowableProxy = (event) -> (event != null)
|
||||
? event.getThrowableProxy() : null;
|
||||
members.add()
|
||||
.whenNotNull(ILoggingEvent::getThrowableProxy)
|
||||
.whenNotNull(getThrowableProxy)
|
||||
.usingMembers((throwableMembers) -> throwableMembers(throwableMembers, extractor));
|
||||
}
|
||||
|
||||
|
@ -128,7 +131,7 @@ class GraylogExtendedLogFormatStructuredLogFormatter extends JsonWriterStructure
|
|||
members.add("_error_message", ILoggingEvent::getThrowableProxy).as(IThrowableProxy::getMessage);
|
||||
}
|
||||
|
||||
private static BinaryOperator<@Nullable String> additionalFieldJoiner() {
|
||||
private static Joiner additionalFieldJoiner() {
|
||||
return (prefix, name) -> {
|
||||
name = prefix + name;
|
||||
if (!FIELD_NAME_VALID_PATTERN.matcher(name).matches()) {
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Iterator;
|
|||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
|
||||
|
@ -76,9 +77,9 @@ class LogstashStructuredLogFormatter extends JsonWriterStructuredLogFormatter<IL
|
|||
.whenNotNull()
|
||||
.as(LogstashStructuredLogFormatter::getMarkers)
|
||||
.whenNotEmpty();
|
||||
members.add("stack_trace", (event) -> event)
|
||||
.whenNotNull(ILoggingEvent::getThrowableProxy)
|
||||
.as(extractor::stackTrace);
|
||||
Function<@Nullable ILoggingEvent, @Nullable Object> getThrowableProxy = (event) -> (event != null)
|
||||
? event.getThrowableProxy() : null;
|
||||
members.add("stack_trace", (event) -> event).whenNotNull(getThrowableProxy).as(extractor::stackTrace);
|
||||
}
|
||||
|
||||
private static String asTimestamp(Instant instant) {
|
||||
|
|
|
@ -21,10 +21,8 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
|
@ -69,8 +67,7 @@ public class ContextPairs {
|
|||
* @param pairs callback to add all the pairs
|
||||
* @return a {@link BiConsumer} for use with the {@link JsonWriter}
|
||||
*/
|
||||
public <T> BiConsumer<T, BiConsumer<String, Object>> flat(BinaryOperator<@Nullable String> joiner,
|
||||
Consumer<Pairs<T>> pairs) {
|
||||
public <T> BiConsumer<T, BiConsumer<String, Object>> flat(Joiner joiner, Consumer<Pairs<T>> pairs) {
|
||||
return (!this.include) ? none() : new Pairs<>(joiner, pairs)::flat;
|
||||
}
|
||||
|
||||
|
@ -89,7 +86,7 @@ public class ContextPairs {
|
|||
};
|
||||
}
|
||||
|
||||
private BinaryOperator<@Nullable String> joinWith(String delimiter) {
|
||||
private Joiner joinWith(String delimiter) {
|
||||
return (prefix, name) -> {
|
||||
StringBuilder joined = new StringBuilder(prefix.length() + delimiter.length() + name.length());
|
||||
joined.append(prefix);
|
||||
|
@ -101,6 +98,22 @@ public class ContextPairs {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins a prefix and a name.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Joiner {
|
||||
|
||||
/**
|
||||
* Joins the given prefix and name.
|
||||
* @param prefix the prefix
|
||||
* @param name the name
|
||||
* @return the joined result or {@code null}
|
||||
*/
|
||||
@Nullable String join(String prefix, String name);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used to add pairs.
|
||||
*
|
||||
|
@ -108,11 +121,11 @@ public class ContextPairs {
|
|||
*/
|
||||
public class Pairs<T> {
|
||||
|
||||
private final BinaryOperator<@Nullable String> joiner;
|
||||
private final Joiner joiner;
|
||||
|
||||
private final List<BiConsumer<T, BiConsumer<String, ?>>> addedPairs;
|
||||
|
||||
Pairs(BinaryOperator<@Nullable String> joiner, Consumer<Pairs<T>> pairs) {
|
||||
Pairs(Joiner joiner, Consumer<Pairs<T>> pairs) {
|
||||
this.joiner = joiner;
|
||||
this.addedPairs = new ArrayList<>();
|
||||
pairs.accept(this);
|
||||
|
@ -120,11 +133,11 @@ public class ContextPairs {
|
|||
|
||||
/**
|
||||
* Add pairs from map entries.
|
||||
* @param <K> the map key type
|
||||
* @param <V> the map value type
|
||||
* @param extractor the extractor used to provide the map
|
||||
*/
|
||||
public <K, V> void addMapEntries(Function<T, Map<String, V>> extractor) {
|
||||
@SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability
|
||||
public <V> void addMapEntries(Function<T, Map<String, V>> extractor) {
|
||||
add(extractor.andThen(Map::entrySet), Map.Entry::getKey, Map.Entry::getValue);
|
||||
}
|
||||
|
||||
|
@ -133,9 +146,8 @@ public class ContextPairs {
|
|||
* @param elementsExtractor the extractor used to provide the iterable
|
||||
* @param pairExtractor the extractor used to provide the name and value
|
||||
* @param <E> the element type
|
||||
* @param <V> the value type
|
||||
*/
|
||||
public <E, V> void add(Function<T, Iterable<E>> elementsExtractor, PairExtractor<E> pairExtractor) {
|
||||
public <E> void add(Function<T, @Nullable Iterable<E>> elementsExtractor, PairExtractor<E> pairExtractor) {
|
||||
add(elementsExtractor, pairExtractor::getName, pairExtractor::getValue);
|
||||
}
|
||||
|
||||
|
@ -147,7 +159,7 @@ public class ContextPairs {
|
|||
* @param nameExtractor the extractor used to provide the name
|
||||
* @param valueExtractor the extractor used to provide the value
|
||||
*/
|
||||
public <E, V> void add(Function<T, Iterable<E>> elementsExtractor, Function<E, String> nameExtractor,
|
||||
public <E, V> void add(Function<T, @Nullable Iterable<E>> elementsExtractor, Function<E, String> nameExtractor,
|
||||
Function<E, V> valueExtractor) {
|
||||
add((item, pairs) -> {
|
||||
Iterable<E> elements = elementsExtractor.apply(item);
|
||||
|
@ -186,7 +198,7 @@ public class ContextPairs {
|
|||
for (int i = 0; i < nameParts.size() - 1; i++) {
|
||||
Object existing = destination.computeIfAbsent(nameParts.get(i), (key) -> new LinkedHashMap<>());
|
||||
if (!(existing instanceof Map)) {
|
||||
String common = nameParts.subList(0, i + 1).stream().collect(Collectors.joining("."));
|
||||
String common = String.join(".", nameParts.subList(0, i + 1));
|
||||
throw new IllegalStateException(
|
||||
"Duplicate nested pairs added under '%s'".formatted(common));
|
||||
}
|
||||
|
@ -196,12 +208,12 @@ public class ContextPairs {
|
|||
Assert.state(previous == null, () -> "Duplicate nested pairs added under '%s'".formatted(name));
|
||||
}));
|
||||
});
|
||||
result.forEach(pairs::accept);
|
||||
result.forEach(pairs);
|
||||
}
|
||||
|
||||
private <V> BiConsumer<String, V> joining(BiConsumer<String, V> pairs) {
|
||||
return (name, value) -> {
|
||||
name = this.joiner.apply(ContextPairs.this.prefix, (name != null) ? name : "");
|
||||
name = this.joiner.join(ContextPairs.this.prefix, (name != null) ? name : "");
|
||||
if (StringUtils.hasLength(name)) {
|
||||
pairs.accept(name, value);
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ public record ElasticCommonSchemaProperties(Service service) {
|
|||
|
||||
static final Service NONE = new Service(null, null, null, null);
|
||||
|
||||
@SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability
|
||||
void jsonMembers(Members<?> members) {
|
||||
members.add("service").usingMembers((service) -> {
|
||||
service.add("name", this::name).whenHasLength();
|
||||
|
|
|
@ -58,6 +58,7 @@ public record GraylogExtendedLogFormatProperties(@Nullable String host, Service
|
|||
* Add {@link JsonWriter} members for the service.
|
||||
* @param members the members to add to
|
||||
*/
|
||||
@SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability
|
||||
public void jsonMembers(JsonWriter.Members<?> members) {
|
||||
members.add("host", this::host).whenHasLength();
|
||||
this.service.jsonMembers(members);
|
||||
|
@ -90,6 +91,7 @@ public record GraylogExtendedLogFormatProperties(@Nullable String host, Service
|
|||
return new Service(version);
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability
|
||||
void jsonMembers(JsonWriter.Members<?> members) {
|
||||
members.add("_service_version", this::version).whenHasLength();
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public final class LambdaSafe {
|
|||
* @return a {@link Callback} instance that can be invoked.
|
||||
*/
|
||||
public static <C, A> Callback<C, A> callback(Class<C> callbackType, C callbackInstance, A argument,
|
||||
Object @Nullable ... additionalArguments) {
|
||||
@Nullable Object @Nullable ... additionalArguments) {
|
||||
Assert.notNull(callbackType, "'callbackType' must not be null");
|
||||
Assert.notNull(callbackInstance, "'callbackInstance' must not be null");
|
||||
return new Callback<>(callbackType, callbackInstance, argument, additionalArguments);
|
||||
|
@ -108,13 +108,13 @@ public final class LambdaSafe {
|
|||
|
||||
private final A argument;
|
||||
|
||||
private final Object @Nullable [] additionalArguments;
|
||||
private final @Nullable Object @Nullable [] additionalArguments;
|
||||
|
||||
private Log logger;
|
||||
|
||||
private Filter<C, A> filter = new GenericTypeFilter<>();
|
||||
|
||||
LambdaSafeCallback(Class<C> callbackType, A argument, Object @Nullable [] additionalArguments) {
|
||||
LambdaSafeCallback(Class<C> callbackType, A argument, @Nullable Object @Nullable [] additionalArguments) {
|
||||
this.callbackType = callbackType;
|
||||
this.argument = argument;
|
||||
this.additionalArguments = additionalArguments;
|
||||
|
@ -175,11 +175,11 @@ public final class LambdaSafe {
|
|||
}
|
||||
|
||||
private boolean startsWithArgumentClassName(String message) {
|
||||
Predicate<Object> startsWith = (argument) -> startsWithArgumentClassName(message, argument);
|
||||
return startsWith.test(this.argument) || additonalArgumentsStartsWith(startsWith);
|
||||
Predicate<@Nullable Object> startsWith = (argument) -> startsWithArgumentClassName(message, argument);
|
||||
return startsWith.test(this.argument) || additionalArgumentsStartsWith(startsWith);
|
||||
}
|
||||
|
||||
private boolean additonalArgumentsStartsWith(Predicate<Object> startsWith) {
|
||||
private boolean additionalArgumentsStartsWith(Predicate<@Nullable Object> startsWith) {
|
||||
if (this.additionalArguments == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ public final class LambdaSafe {
|
|||
private final C callbackInstance;
|
||||
|
||||
private Callback(Class<C> callbackType, C callbackInstance, A argument,
|
||||
Object @Nullable [] additionalArguments) {
|
||||
@Nullable Object @Nullable [] additionalArguments) {
|
||||
super(callbackType, argument, additionalArguments);
|
||||
this.callbackInstance = callbackInstance;
|
||||
}
|
||||
|
@ -343,7 +343,8 @@ public final class LambdaSafe {
|
|||
* @param additionalArguments any additional arguments
|
||||
* @return if the callback matches and should be invoked
|
||||
*/
|
||||
boolean match(Class<C> callbackType, C callbackInstance, A argument, Object @Nullable [] additionalArguments);
|
||||
boolean match(Class<C> callbackType, C callbackInstance, A argument,
|
||||
@Nullable Object @Nullable [] additionalArguments);
|
||||
|
||||
/**
|
||||
* Return a {@link Filter} that allows all callbacks to be invoked.
|
||||
|
@ -365,7 +366,7 @@ public final class LambdaSafe {
|
|||
|
||||
@Override
|
||||
public boolean match(Class<C> callbackType, C callbackInstance, A argument,
|
||||
Object @Nullable [] additionalArguments) {
|
||||
@Nullable Object @Nullable [] additionalArguments) {
|
||||
ResolvableType type = ResolvableType.forClass(callbackType, callbackInstance.getClass());
|
||||
if (type.getGenerics().length != 1) {
|
||||
return true;
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
|
||||
package smoketest.structuredlogging;
|
||||
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.json.JsonWriter.Members;
|
||||
import org.springframework.boot.json.JsonWriter.ValueProcessor;
|
||||
import org.springframework.boot.logging.structured.StructuredLoggingJsonMembersCustomizer;
|
||||
|
@ -24,8 +28,9 @@ public class SampleJsonMembersCustomizer implements StructuredLoggingJsonMembers
|
|||
|
||||
@Override
|
||||
public void customize(Members<Object> members) {
|
||||
UnaryOperator<@Nullable String> formatted = "!!%s!!"::formatted;
|
||||
members.applyingValueProcessor(
|
||||
ValueProcessor.of(String.class, "!!%s!!"::formatted).whenHasUnescapedPath("process.thread.name"));
|
||||
ValueProcessor.of(String.class, formatted).whenHasUnescapedPath("process.thread.name"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue