Skip to content

Commit 4c72ce6

Browse files
committed
Merge branch '3.5.x'
Closes gh-46481
2 parents 51a6b5e + b0350a5 commit 4c72ce6

17 files changed

+231
-48
lines changed

config/checkstyle/checkstyle-suppressions.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,5 @@
8484
<suppress files="SpringBootBanner\.java" checks="SpringLeadingWhitespace" />
8585
<suppress files="LoadTimeWeaverAwareConsumerContainers\.java" checks="InterfaceIsType" />
8686
<suppress files="ConfigurationPropertyCaching\.java" checks="SpringJavadoc" message="\@since"/>
87+
<suppress files="StructuredLoggingJsonMembersCustomizer\.java" checks="SpringJavadoc" message="\@since"/>
8788
</suppressions>

core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/ElasticCommonSchemaStructuredLogFormatter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@
4949
class ElasticCommonSchemaStructuredLogFormatter extends JsonWriterStructuredLogFormatter<LogEvent> {
5050

5151
ElasticCommonSchemaStructuredLogFormatter(Environment environment, StackTracePrinter stackTracePrinter,
52-
ContextPairs contextPairs, StructuredLoggingJsonMembersCustomizer<?> customizer) {
53-
super((members) -> jsonMembers(environment, stackTracePrinter, contextPairs, members), customizer);
52+
ContextPairs contextPairs, StructuredLoggingJsonMembersCustomizer.Builder<?> customizerBuilder) {
53+
super((members) -> jsonMembers(environment, stackTracePrinter, contextPairs, members),
54+
customizerBuilder.nested().build());
5455
}
5556

5657
private static void jsonMembers(Environment environment, StackTracePrinter stackTracePrinter,

core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/StructuredLogLayout.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ private ElasticCommonSchemaStructuredLogFormatter createEcsFormatter(Instantiato
115115
Environment environment = instantiator.getArg(Environment.class);
116116
StackTracePrinter stackTracePrinter = instantiator.getArg(StackTracePrinter.class);
117117
ContextPairs contextPairs = instantiator.getArg(ContextPairs.class);
118-
StructuredLoggingJsonMembersCustomizer<?> jsonMembersCustomizer = instantiator
119-
.getArg(StructuredLoggingJsonMembersCustomizer.class);
118+
StructuredLoggingJsonMembersCustomizer.Builder<?> jsonMembersCustomizerBuilder = instantiator
119+
.getArg(StructuredLoggingJsonMembersCustomizer.Builder.class);
120120
return new ElasticCommonSchemaStructuredLogFormatter(environment, stackTracePrinter, contextPairs,
121-
jsonMembersCustomizer);
121+
jsonMembersCustomizerBuilder);
122122
}
123123

124124
private GraylogExtendedLogFormatStructuredLogFormatter createGraylogFormatter(Instantiator<?> instantiator) {

core/spring-boot/src/main/java/org/springframework/boot/logging/logback/ElasticCommonSchemaStructuredLogFormatter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ class ElasticCommonSchemaStructuredLogFormatter extends JsonWriterStructuredLogF
5353

5454
ElasticCommonSchemaStructuredLogFormatter(Environment environment, StackTracePrinter stackTracePrinter,
5555
ContextPairs contextPairs, ThrowableProxyConverter throwableProxyConverter,
56-
StructuredLoggingJsonMembersCustomizer<?> customizer) {
56+
StructuredLoggingJsonMembersCustomizer.Builder<?> customizerBuilder) {
5757
super((members) -> jsonMembers(environment, stackTracePrinter, contextPairs, throwableProxyConverter, members),
58-
customizer);
58+
customizerBuilder.nested().build());
5959
}
6060

6161
private static void jsonMembers(Environment environment, StackTracePrinter stackTracePrinter,

core/spring-boot/src/main/java/org/springframework/boot/logging/logback/StructuredLogEncoder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,10 @@ private StructuredLogFormatter<ILoggingEvent> createEcsFormatter(Instantiator<?>
9393
StackTracePrinter stackTracePrinter = instantiator.getArg(StackTracePrinter.class);
9494
ContextPairs contextParis = instantiator.getArg(ContextPairs.class);
9595
ThrowableProxyConverter throwableProxyConverter = instantiator.getArg(ThrowableProxyConverter.class);
96-
StructuredLoggingJsonMembersCustomizer<?> jsonMembersCustomizer = instantiator
97-
.getArg(StructuredLoggingJsonMembersCustomizer.class);
96+
StructuredLoggingJsonMembersCustomizer.Builder<?> jsonMembersCustomizerBuilder = instantiator
97+
.getArg(StructuredLoggingJsonMembersCustomizer.Builder.class);
9898
return new ElasticCommonSchemaStructuredLogFormatter(environment, stackTracePrinter, contextParis,
99-
throwableProxyConverter, jsonMembersCustomizer);
99+
throwableProxyConverter, jsonMembersCustomizerBuilder);
100100
}
101101

102102
private StructuredLogFormatter<ILoggingEvent> createGraylogFormatter(Instantiator<?> instantiator) {

core/spring-boot/src/main/java/org/springframework/boot/logging/structured/StructuredLogFormatter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
* <ul>
2929
* <li>{@link Environment}</li>
3030
* <li>{@link StructuredLoggingJsonMembersCustomizer}</li>
31+
* <li>{@link StructuredLoggingJsonMembersCustomizer.Builder}</li>
3132
* <li>{@link StackTracePrinter} (may be {@code null})</li>
3233
* <li>{@link ContextPairs}</li>
3334
* </ul>

core/spring-boot/src/main/java/org/springframework/boot/logging/structured/StructuredLogFormatterFactory.java

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.boot.util.Instantiator;
3030
import org.springframework.boot.util.Instantiator.AvailableParameters;
3131
import org.springframework.boot.util.Instantiator.FailureHandler;
32+
import org.springframework.boot.util.LambdaSafe;
3233
import org.springframework.core.GenericTypeResolver;
3334
import org.springframework.core.env.Environment;
3435
import org.springframework.core.io.support.SpringFactoriesLoader;
@@ -85,7 +86,9 @@ public StructuredLogFormatterFactory(Class<E> logEventType, Environment environm
8586
this.instantiator = new Instantiator<>(Object.class, (allAvailableParameters) -> {
8687
allAvailableParameters.add(Environment.class, environment);
8788
allAvailableParameters.add(StructuredLoggingJsonMembersCustomizer.class,
88-
(type) -> getStructuredLoggingJsonMembersCustomizer(properties));
89+
new JsonMembersCustomizerBuilder(properties).build());
90+
allAvailableParameters.add(StructuredLoggingJsonMembersCustomizer.Builder.class,
91+
new JsonMembersCustomizerBuilder(properties));
8992
allAvailableParameters.add(StackTracePrinter.class, (type) -> getStackTracePrinter(properties));
9093
allAvailableParameters.add(ContextPairs.class, (type) -> getContextPairs(properties));
9194
if (availableParameters != null) {
@@ -96,30 +99,6 @@ public StructuredLogFormatterFactory(Class<E> logEventType, Environment environm
9699
commonFormatters.accept(this.commonFormatters);
97100
}
98101

99-
StructuredLoggingJsonMembersCustomizer<?> getStructuredLoggingJsonMembersCustomizer(
100-
StructuredLoggingJsonProperties properties) {
101-
List<StructuredLoggingJsonMembersCustomizer<?>> customizers = new ArrayList<>();
102-
if (properties != null) {
103-
customizers.add(new StructuredLoggingJsonPropertiesJsonMembersCustomizer(this.instantiator, properties));
104-
}
105-
customizers.addAll(loadStructuredLoggingJsonMembersCustomizers());
106-
return (members) -> invokeCustomizers(customizers, members);
107-
}
108-
109-
@SuppressWarnings({ "unchecked", "rawtypes" })
110-
private List<StructuredLoggingJsonMembersCustomizer<?>> loadStructuredLoggingJsonMembersCustomizers() {
111-
return (List) this.factoriesLoader.load(StructuredLoggingJsonMembersCustomizer.class,
112-
ArgumentResolver.from(this.instantiator::getArg));
113-
}
114-
115-
@SuppressWarnings({ "unchecked", "rawtypes" })
116-
private void invokeCustomizers(List<StructuredLoggingJsonMembersCustomizer<?>> customizers,
117-
Members<Object> members) {
118-
for (StructuredLoggingJsonMembersCustomizer<?> customizer : customizers) {
119-
((StructuredLoggingJsonMembersCustomizer) customizer).customize(members);
120-
}
121-
}
122-
123102
private StackTracePrinter getStackTracePrinter(StructuredLoggingJsonProperties properties) {
124103
return (properties != null && properties.stackTrace() != null) ? properties.stackTrace().createPrinter() : null;
125104
}
@@ -218,4 +197,53 @@ public interface CommonFormatterFactory<E> {
218197

219198
}
220199

200+
/**
201+
* {@link StructuredLoggingJsonMembersCustomizer.Builder} implementation.
202+
*/
203+
class JsonMembersCustomizerBuilder implements StructuredLoggingJsonMembersCustomizer.Builder<E> {
204+
205+
private final StructuredLoggingJsonProperties properties;
206+
207+
private boolean nested;
208+
209+
JsonMembersCustomizerBuilder(StructuredLoggingJsonProperties properties) {
210+
this.properties = properties;
211+
}
212+
213+
@Override
214+
public JsonMembersCustomizerBuilder nested(boolean nested) {
215+
this.nested = nested;
216+
return this;
217+
}
218+
219+
@Override
220+
public StructuredLoggingJsonMembersCustomizer<E> build() {
221+
return (members) -> {
222+
List<StructuredLoggingJsonMembersCustomizer<?>> customizers = new ArrayList<>();
223+
if (this.properties != null) {
224+
customizers.add(new StructuredLoggingJsonPropertiesJsonMembersCustomizer(
225+
StructuredLogFormatterFactory.this.instantiator, this.properties, this.nested));
226+
}
227+
customizers.addAll(loadStructuredLoggingJsonMembersCustomizers());
228+
invokeCustomizers(members, customizers);
229+
};
230+
}
231+
232+
@SuppressWarnings({ "unchecked", "rawtypes" })
233+
private List<StructuredLoggingJsonMembersCustomizer<?>> loadStructuredLoggingJsonMembersCustomizers() {
234+
return (List) StructuredLogFormatterFactory.this.factoriesLoader.load(
235+
StructuredLoggingJsonMembersCustomizer.class,
236+
ArgumentResolver.from(StructuredLogFormatterFactory.this.instantiator::getArg));
237+
}
238+
239+
@SuppressWarnings("unchecked")
240+
private void invokeCustomizers(Members<E> members,
241+
List<StructuredLoggingJsonMembersCustomizer<?>> customizers) {
242+
LambdaSafe.callbacks(StructuredLoggingJsonMembersCustomizer.class, customizers, members)
243+
.withFilter(LambdaSafe.Filter.allowAll())
244+
.invoke((customizer) -> customizer.customize(members));
245+
}
246+
247+
}
248+
221249
}

core/spring-boot/src/main/java/org/springframework/boot/logging/structured/StructuredLoggingJsonMembersCustomizer.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,37 @@ public interface StructuredLoggingJsonMembersCustomizer<T> {
5353
*/
5454
void customize(JsonWriter.Members<T> members);
5555

56+
/**
57+
* Builder that can be injected into a {@link StructuredLogFormatter} to build the
58+
* {@link StructuredLoggingJsonMembersCustomizer} when specific settings are required.
59+
*
60+
* @param <T> the type being written
61+
* @since 3.5.4
62+
*/
63+
interface Builder<T> {
64+
65+
/**
66+
* Use nested fields when adding JSON from user defined properties.
67+
* @return this builder
68+
*/
69+
default Builder<T> nested() {
70+
return nested(true);
71+
}
72+
73+
/**
74+
* Set if nested fields should be used when adding JSON from user defined
75+
* properties.
76+
* @param nested if nested fields are to be used
77+
* @return this builder
78+
*/
79+
Builder<T> nested(boolean nested);
80+
81+
/**
82+
* Build the {@link StructuredLoggingJsonMembersCustomizer}.
83+
* @return the built customizer
84+
*/
85+
StructuredLoggingJsonMembersCustomizer<T> build();
86+
87+
}
88+
5689
}

core/spring-boot/src/main/java/org/springframework/boot/logging/structured/StructuredLoggingJsonPropertiesJsonMembersCustomizer.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@ class StructuredLoggingJsonPropertiesJsonMembersCustomizer implements Structured
3636

3737
private final StructuredLoggingJsonProperties properties;
3838

39+
private final boolean nested;
40+
3941
StructuredLoggingJsonPropertiesJsonMembersCustomizer(Instantiator<?> instantiator,
40-
StructuredLoggingJsonProperties properties) {
42+
StructuredLoggingJsonProperties properties, boolean nested) {
4143
this.instantiator = instantiator;
4244
this.properties = properties;
45+
this.nested = nested;
4346
}
4447

4548
@Override
@@ -48,7 +51,13 @@ public void customize(Members<Object> members) {
4851
members.applyingNameProcessor(this::renameJsonMembers);
4952
Map<String, String> add = this.properties.add();
5053
if (!CollectionUtils.isEmpty(add)) {
51-
add.forEach(members::add);
54+
if (this.nested) {
55+
ContextPairs contextPairs = new ContextPairs(true, "");
56+
members.add().usingPairs(contextPairs.nested((pairs) -> pairs.addMapEntries((source) -> add)));
57+
}
58+
else {
59+
add.forEach(members::add);
60+
}
5261
}
5362
this.properties.customizers(this.instantiator).forEach((customizer) -> customizer.customize(members));
5463
}

core/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/AbstractStructuredLoggingTests.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.mockito.Mock;
3232
import org.mockito.junit.jupiter.MockitoExtension;
3333

34+
import org.springframework.boot.logging.structured.MockStructuredLoggingJsonMembersCustomizerBuilder;
3435
import org.springframework.boot.logging.structured.StructuredLoggingJsonMembersCustomizer;
3536

3637
import static org.assertj.core.api.Assertions.assertThat;
@@ -50,6 +51,9 @@ abstract class AbstractStructuredLoggingTests {
5051
@Mock
5152
StructuredLoggingJsonMembersCustomizer<?> customizer;
5253

54+
MockStructuredLoggingJsonMembersCustomizerBuilder<?> customizerBuilder = new MockStructuredLoggingJsonMembersCustomizerBuilder<>(
55+
() -> this.customizer);
56+
5357
protected Map<String, Object> map(Object... values) {
5458
assertThat(values.length).isEven();
5559
Map<String, Object> result = new HashMap<>();

0 commit comments

Comments
 (0)