Skip to content

Commit c1cb4c5

Browse files
committed
Use a single customizer property for JSON logging
Update `StructuredLoggingJsonProperties` no that only a single `customizer` property is supported. See gh-43368
1 parent 035c80a commit c1cb4c5

File tree

7 files changed

+21
-61
lines changed

7 files changed

+21
-61
lines changed

spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/features/logging.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ logging:
642642
----
643643

644644
TIP: For more advanced customizations, you can use the javadoc:org.springframework.boot.logging.structured.StructuredLoggingJsonMembersCustomizer[] interface.
645-
You can reference a single implementation using the configprop:logging.structured.json.customizer[] property, or use configprop:logging.structured.json.customizers[] if you have more than one.
645+
You can reference a one or more implementations using the configprop:logging.structured.json.customizer[] property.
646646
You can also declare implementations by listing them in a `META-INF/spring.factories` file.
647647

648648

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/structured/StructuredLoggingJsonMembersCustomizerBeanFactoryInitializationAotProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class StructuredLoggingJsonMembersCustomizerBeanFactoryInitializationAotProcesso
4545
public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) {
4646
Environment environment = beanFactory.getBean(ENVIRONMENT_BEAN_NAME, Environment.class);
4747
StructuredLoggingJsonProperties properties = StructuredLoggingJsonProperties.get(environment);
48-
return (properties != null) ? AotContribution.get(properties.allCustomizers()) : null;
48+
return (properties != null) ? AotContribution.get(properties.customizer()) : null;
4949
}
5050

5151
private static final class AotContribution implements BeanFactoryInitializationAotContribution {

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/structured/StructuredLoggingJsonProperties.java

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,14 @@
1818

1919
import java.util.Collection;
2020
import java.util.Collections;
21-
import java.util.LinkedHashSet;
21+
import java.util.List;
2222
import java.util.Map;
2323
import java.util.Set;
2424

2525
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrar;
2626
import org.springframework.boot.context.properties.bind.Binder;
2727
import org.springframework.boot.util.Instantiator;
2828
import org.springframework.core.env.Environment;
29-
import org.springframework.util.CollectionUtils;
3029

3130
/**
3231
* Properties that can be used to customize structured logging JSON.
@@ -35,42 +34,21 @@
3534
* @param exclude the paths that should be excluded. An empty set excludes nothing
3635
* @param rename a map of path to replacement names
3736
* @param add a map of additional elements {@link StructuredLoggingJsonMembersCustomizer}
38-
* @param customizer the fully qualified name of a
39-
* {@link StructuredLoggingJsonMembersCustomizer} implementation
40-
* @param customizers the fully qualified names of
37+
* @param customizer the fully qualified names of
4138
* {@link StructuredLoggingJsonMembersCustomizer} implementations
4239
* @author Phillip Webb
4340
* @author Yanming Zhou
4441
*/
4542
record StructuredLoggingJsonProperties(Set<String> include, Set<String> exclude, Map<String, String> rename,
46-
Map<String, String> add, Class<? extends StructuredLoggingJsonMembersCustomizer<?>> customizer,
47-
Set<Class<? extends StructuredLoggingJsonMembersCustomizer<?>>> customizers) {
43+
Map<String, String> add, Set<Class<? extends StructuredLoggingJsonMembersCustomizer<?>>> customizer) {
4844

49-
Collection<StructuredLoggingJsonMembersCustomizer<Object>> allCustomizers(Instantiator<?> instantiator) {
50-
return allCustomizers().stream().map((customizer) -> instantiateCustomizer(instantiator, customizer)).toList();
45+
StructuredLoggingJsonProperties {
46+
customizer = (customizer != null) ? customizer : Collections.emptySet();
5147
}
5248

53-
Set<Class<? extends StructuredLoggingJsonMembersCustomizer<?>>> allCustomizers() {
54-
return merge(customizer(), customizers());
55-
}
56-
57-
private <T> Set<T> merge(T element, Set<T> elements) {
58-
if (CollectionUtils.isEmpty(elements)) {
59-
return (element != null) ? Set.of(element) : Collections.emptySet();
60-
}
61-
if (element == null) {
62-
return elements;
63-
}
64-
Set<T> result = new LinkedHashSet<>(elements.size() + 1);
65-
result.add(element);
66-
result.addAll(elements);
67-
return result;
68-
}
69-
70-
@SuppressWarnings("unchecked")
71-
private StructuredLoggingJsonMembersCustomizer<Object> instantiateCustomizer(Instantiator<?> instantiator,
72-
Class<? extends StructuredLoggingJsonMembersCustomizer<?>> customizer) {
73-
return (StructuredLoggingJsonMembersCustomizer<Object>) instantiator.instantiateType(customizer);
49+
@SuppressWarnings({ "unchecked", "rawtypes" })
50+
Collection<StructuredLoggingJsonMembersCustomizer<Object>> customizers(Instantiator<?> instantiator) {
51+
return (List) customizer().stream().map(instantiator::instantiateType).toList();
7452
}
7553

7654
static StructuredLoggingJsonProperties get(Environment environment) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public void customize(Members<Object> members) {
5050
if (!CollectionUtils.isEmpty(add)) {
5151
add.forEach(members::add);
5252
}
53-
this.properties.allCustomizers(this.instantiator).forEach((customizer) -> customizer.customize(members));
53+
this.properties.customizers(this.instantiator).forEach((customizer) -> customizer.customize(members));
5454
}
5555

5656
String renameJsonMembers(MemberPath path, String existingName) {

spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,10 @@
266266
"type": "java.util.Map<java.lang.String,java.lang.String>",
267267
"description": "Additional members that should be added to structured logging JSON"
268268
},
269-
{
270-
"name": "logging.structured.json.customizer",
271-
"type": "java.lang.Class<? extends org.springframework.boot.logging.structured.StructuredLoggingJsonMembersCustomizer<?>>",
272-
"description": "The fully qualified class name of a StructuredLoggingJsonMembersCustomizer"
273-
},
274269
{
275270
"name": "logging.structured.json.customizers",
276271
"type": "java.util.Set<java.lang.Class<? extends org.springframework.boot.logging.structured.StructuredLoggingJsonMembersCustomizer<?>>>",
277-
"description": "The fully qualified class names of a StructuredLoggingJsonMembersCustomizer"
272+
"description": "Fully qualified class names of StructuredLoggingJsonMembersCustomizer implementations"
278273
},
279274
{
280275
"name": "logging.structured.json.exclude",

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/structured/StructuredLoggingJsonPropertiesJsonMembersCustomizerTests.java

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class StructuredLoggingJsonPropertiesJsonMembersCustomizerTests {
4848
@Test
4949
void customizeWhenHasExcludeFiltersMember() {
5050
StructuredLoggingJsonProperties properties = new StructuredLoggingJsonProperties(Collections.emptySet(),
51-
Set.of("a"), Collections.emptyMap(), Collections.emptyMap(), null, null);
51+
Set.of("a"), Collections.emptyMap(), Collections.emptyMap(), null);
5252
StructuredLoggingJsonPropertiesJsonMembersCustomizer customizer = new StructuredLoggingJsonPropertiesJsonMembersCustomizer(
5353
this.instantiator, properties);
5454
assertThat(writeSampleJson(customizer)).doesNotContain("a").contains("b");
@@ -57,7 +57,7 @@ void customizeWhenHasExcludeFiltersMember() {
5757
@Test
5858
void customizeWhenHasIncludeFiltersOtherMembers() {
5959
StructuredLoggingJsonProperties properties = new StructuredLoggingJsonProperties(Set.of("a"),
60-
Collections.emptySet(), Collections.emptyMap(), Collections.emptyMap(), null, null);
60+
Collections.emptySet(), Collections.emptyMap(), Collections.emptyMap(), null);
6161
StructuredLoggingJsonPropertiesJsonMembersCustomizer customizer = new StructuredLoggingJsonPropertiesJsonMembersCustomizer(
6262
this.instantiator, properties);
6363
assertThat(writeSampleJson(customizer)).contains("a")
@@ -69,7 +69,7 @@ void customizeWhenHasIncludeFiltersOtherMembers() {
6969
@Test
7070
void customizeWhenHasIncludeAndExcludeFiltersMembers() {
7171
StructuredLoggingJsonProperties properties = new StructuredLoggingJsonProperties(Set.of("a", "b"), Set.of("b"),
72-
Collections.emptyMap(), Collections.emptyMap(), null, null);
72+
Collections.emptyMap(), Collections.emptyMap(), null);
7373
StructuredLoggingJsonPropertiesJsonMembersCustomizer customizer = new StructuredLoggingJsonPropertiesJsonMembersCustomizer(
7474
this.instantiator, properties);
7575
assertThat(writeSampleJson(customizer)).contains("a")
@@ -81,7 +81,7 @@ void customizeWhenHasIncludeAndExcludeFiltersMembers() {
8181
@Test
8282
void customizeWhenHasRenameRenamesMember() {
8383
StructuredLoggingJsonProperties properties = new StructuredLoggingJsonProperties(Collections.emptySet(),
84-
Collections.emptySet(), Map.of("a", "z"), Collections.emptyMap(), null, null);
84+
Collections.emptySet(), Map.of("a", "z"), Collections.emptyMap(), null);
8585
StructuredLoggingJsonPropertiesJsonMembersCustomizer customizer = new StructuredLoggingJsonPropertiesJsonMembersCustomizer(
8686
this.instantiator, properties);
8787
assertThat(writeSampleJson(customizer)).contains("\"z\":\"a\"");
@@ -90,7 +90,7 @@ void customizeWhenHasRenameRenamesMember() {
9090
@Test
9191
void customizeWhenHasAddAddsMemeber() {
9292
StructuredLoggingJsonProperties properties = new StructuredLoggingJsonProperties(Collections.emptySet(),
93-
Collections.emptySet(), Collections.emptyMap(), Map.of("z", "z"), null, null);
93+
Collections.emptySet(), Collections.emptyMap(), Map.of("z", "z"), null);
9494
StructuredLoggingJsonPropertiesJsonMembersCustomizer customizer = new StructuredLoggingJsonPropertiesJsonMembersCustomizer(
9595
this.instantiator, properties);
9696
assertThat(writeSampleJson(customizer)).contains("\"z\":\"z\"");
@@ -103,7 +103,7 @@ void customizeWhenHasCustomizerCustomizesMember() {
103103
.applyingNameProcessor(NameProcessor.of(String::toUpperCase));
104104
given(((Instantiator) this.instantiator).instantiateType(TestCustomizer.class)).willReturn(uppercaseCustomizer);
105105
StructuredLoggingJsonProperties properties = new StructuredLoggingJsonProperties(Collections.emptySet(),
106-
Collections.emptySet(), Collections.emptyMap(), Collections.emptyMap(), TestCustomizer.class, null);
106+
Collections.emptySet(), Collections.emptyMap(), Collections.emptyMap(), Set.of(TestCustomizer.class));
107107
StructuredLoggingJsonPropertiesJsonMembersCustomizer customizer = new StructuredLoggingJsonPropertiesJsonMembersCustomizer(
108108
this.instantiator, properties);
109109
assertThat(writeSampleJson(customizer)).contains("\"A\":\"a\"");
@@ -115,26 +115,13 @@ void customizeWhenHasCustomizersCustomizesMember() {
115115
given(((Instantiator) this.instantiator).instantiateType(FooCustomizer.class)).willReturn(new FooCustomizer());
116116
given(((Instantiator) this.instantiator).instantiateType(BarCustomizer.class)).willReturn(new BarCustomizer());
117117
StructuredLoggingJsonProperties properties = new StructuredLoggingJsonProperties(Collections.emptySet(),
118-
Collections.emptySet(), Collections.emptyMap(), Collections.emptyMap(), null,
118+
Collections.emptySet(), Collections.emptyMap(), Collections.emptyMap(),
119119
Set.of(FooCustomizer.class, BarCustomizer.class));
120120
StructuredLoggingJsonPropertiesJsonMembersCustomizer customizer = new StructuredLoggingJsonPropertiesJsonMembersCustomizer(
121121
this.instantiator, properties);
122122
assertThat(writeSampleJson(customizer)).contains("\"foo\":\"foo\"").contains("\"bar\":\"bar\"");
123123
}
124124

125-
@Test
126-
@SuppressWarnings({ "rawtypes", "unchecked" })
127-
void customizeWhenHasCustomizerAndCustomizersCustomizesMember() {
128-
given(((Instantiator) this.instantiator).instantiateType(FooCustomizer.class)).willReturn(new FooCustomizer());
129-
given(((Instantiator) this.instantiator).instantiateType(BarCustomizer.class)).willReturn(new BarCustomizer());
130-
StructuredLoggingJsonProperties properties = new StructuredLoggingJsonProperties(Collections.emptySet(),
131-
Collections.emptySet(), Collections.emptyMap(), Collections.emptyMap(), FooCustomizer.class,
132-
Set.of(BarCustomizer.class));
133-
StructuredLoggingJsonPropertiesJsonMembersCustomizer customizer = new StructuredLoggingJsonPropertiesJsonMembersCustomizer(
134-
this.instantiator, properties);
135-
assertThat(writeSampleJson(customizer)).contains("\"foo\":\"foo\"").contains("\"bar\":\"bar\"");
136-
}
137-
138125
@SuppressWarnings({ "rawtypes", "unchecked" })
139126
private String writeSampleJson(StructuredLoggingJsonMembersCustomizer customizer) {
140127
return JsonWriter.of((members) -> {

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/structured/StructuredLoggingJsonPropertiesTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ void getBindsFromEnvironment() {
4848
environment.setProperty("logging.structured.json.customizer", TestCustomizer.class.getName());
4949
StructuredLoggingJsonProperties properties = StructuredLoggingJsonProperties.get(environment);
5050
assertThat(properties).isEqualTo(new StructuredLoggingJsonProperties(Set.of("a", "b"), Set.of("c", "d"),
51-
Map.of("e", "f"), Map.of("g", "h"), TestCustomizer.class, null));
51+
Map.of("e", "f"), Map.of("g", "h"), Set.of(TestCustomizer.class)));
5252
}
5353

5454
@Test
@@ -64,7 +64,7 @@ void shouldRegisterRuntimeHints() throws Exception {
6464
assertThat(RuntimeHintsPredicates.reflection().onType(StructuredLoggingJsonProperties.class)).accepts(hints);
6565
assertThat(RuntimeHintsPredicates.reflection()
6666
.onConstructor(StructuredLoggingJsonProperties.class.getDeclaredConstructor(Set.class, Set.class, Map.class,
67-
Map.class, Class.class, Set.class))
67+
Map.class, Set.class))
6868
.invoke()).accepts(hints);
6969
}
7070

0 commit comments

Comments
 (0)