Skip to content

Commit 763266f

Browse files
committed
Rationalize structured logging service classes
Rename `ElasticCommonSchemaService` & `GraylogExtendedLogFormatService` and change a few of the property names. The `Service` suffix was originally chosen because ECS uses the term, but `Properties` is more common in the Spring Boot codebase and works better for Graylog. Closes gh-42578
1 parent aed4546 commit 763266f

14 files changed

+236
-182
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -524,19 +524,19 @@ A log line looks like this:
524524
This format also adds every key value pair contained in the MDC to the JSON object.
525525
You can also use the https://www.slf4j.org/manual.html#fluent[SLF4J fluent logging API] to add key value pairs to the logged JSON object with the https://www.slf4j.org/apidocs/org/slf4j/spi/LoggingEventBuilder.html#addKeyValue(java.lang.String,java.lang.Object)[addKeyValue] method.
526526

527-
The `service` values can be customized using `logging.structured.gelf.service` properties:
527+
Several fields can be customized using `logging.structured.gelf` properties:
528528

529529
[configprops,yaml]
530530
----
531531
logging:
532532
structured:
533533
gelf:
534+
host: MyService
534535
service:
535-
name: MyService
536536
version: 1.0
537537
----
538538

539-
NOTE: configprop:logging.structured.gelf.service.name[] will default to configprop:spring.application.name[] if not specified.
539+
NOTE: configprop:logging.structured.gelf.host[] will default to configprop:spring.application.name[] if not specified.
540540

541541
NOTE: configprop:logging.structured.gelf.service.version[] will default to configprop:spring.application.version[] if not specified.
542542

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
import org.springframework.boot.json.JsonWriter;
2828
import org.springframework.boot.logging.structured.CommonStructuredLogFormat;
29-
import org.springframework.boot.logging.structured.ElasticCommonSchemaService;
29+
import org.springframework.boot.logging.structured.ElasticCommonSchemaProperties;
3030
import org.springframework.boot.logging.structured.JsonWriterStructuredLogFormatter;
3131
import org.springframework.boot.logging.structured.StructuredLogFormatter;
3232
import org.springframework.core.env.Environment;
@@ -51,7 +51,7 @@ private static void jsonMembers(Environment environment, JsonWriter.Members<LogE
5151
members.add("process.pid", environment.getProperty("spring.application.pid", Long.class))
5252
.when(Objects::nonNull);
5353
members.add("process.thread.name", LogEvent::getThreadName);
54-
ElasticCommonSchemaService.get(environment).jsonMembers(members);
54+
ElasticCommonSchemaProperties.get(environment).jsonMembers(members);
5555
members.add("log.logger", LogEvent::getLoggerName);
5656
members.add("message", LogEvent::getMessage).as(StructuredMessage::get);
5757
members.from(LogEvent::getContextData)

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/GraylogExtendedLogFormatStructuredLogFormatter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import org.springframework.boot.json.JsonWriter.Members;
3636
import org.springframework.boot.json.WritableJson;
3737
import org.springframework.boot.logging.structured.CommonStructuredLogFormat;
38-
import org.springframework.boot.logging.structured.GraylogExtendedLogFormatService;
38+
import org.springframework.boot.logging.structured.GraylogExtendedLogFormatProperties;
3939
import org.springframework.boot.logging.structured.JsonWriterStructuredLogFormatter;
4040
import org.springframework.boot.logging.structured.StructuredLogFormatter;
4141
import org.springframework.core.env.Environment;
@@ -83,7 +83,7 @@ private static void jsonMembers(Environment environment, JsonWriter.Members<LogE
8383
members.add("_process_pid", environment.getProperty("spring.application.pid", Long.class))
8484
.when(Objects::nonNull);
8585
members.add("_process_thread_name", LogEvent::getThreadName);
86-
GraylogExtendedLogFormatService.get(environment).jsonMembers(members);
86+
GraylogExtendedLogFormatProperties.get(environment).jsonMembers(members);
8787
members.add("_log_logger", LogEvent::getLoggerName);
8888
members.from(LogEvent::getContextData)
8989
.whenNot(ReadOnlyStringMap::isEmpty)

spring-boot-project/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
@@ -26,7 +26,7 @@
2626
import org.springframework.boot.json.JsonWriter;
2727
import org.springframework.boot.json.JsonWriter.PairExtractor;
2828
import org.springframework.boot.logging.structured.CommonStructuredLogFormat;
29-
import org.springframework.boot.logging.structured.ElasticCommonSchemaService;
29+
import org.springframework.boot.logging.structured.ElasticCommonSchemaProperties;
3030
import org.springframework.boot.logging.structured.JsonWriterStructuredLogFormatter;
3131
import org.springframework.boot.logging.structured.StructuredLogFormatter;
3232
import org.springframework.core.env.Environment;
@@ -55,7 +55,7 @@ private static void jsonMembers(Environment environment, ThrowableProxyConverter
5555
members.add("process.pid", environment.getProperty("spring.application.pid", Long.class))
5656
.when(Objects::nonNull);
5757
members.add("process.thread.name", ILoggingEvent::getThreadName);
58-
ElasticCommonSchemaService.get(environment).jsonMembers(members);
58+
ElasticCommonSchemaProperties.get(environment).jsonMembers(members);
5959
members.add("log.logger", ILoggingEvent::getLoggerName);
6060
members.add("message", ILoggingEvent::getFormattedMessage);
6161
members.addMapEntries(ILoggingEvent::getMDCPropertyMap);

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/GraylogExtendedLogFormatStructuredLogFormatter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import org.springframework.boot.json.JsonWriter.Members;
3636
import org.springframework.boot.json.WritableJson;
3737
import org.springframework.boot.logging.structured.CommonStructuredLogFormat;
38-
import org.springframework.boot.logging.structured.GraylogExtendedLogFormatService;
38+
import org.springframework.boot.logging.structured.GraylogExtendedLogFormatProperties;
3939
import org.springframework.boot.logging.structured.JsonWriterStructuredLogFormatter;
4040
import org.springframework.boot.logging.structured.StructuredLogFormatter;
4141
import org.springframework.core.env.Environment;
@@ -85,7 +85,7 @@ private static void jsonMembers(Environment environment, ThrowableProxyConverter
8585
members.add("_process_pid", environment.getProperty("spring.application.pid", Long.class))
8686
.when(Objects::nonNull);
8787
members.add("_process_thread_name", ILoggingEvent::getThreadName);
88-
GraylogExtendedLogFormatService.get(environment).jsonMembers(members);
88+
GraylogExtendedLogFormatProperties.get(environment).jsonMembers(members);
8989
members.add("_log_logger", ILoggingEvent::getLoggerName);
9090
members.from(ILoggingEvent::getMDCPropertyMap)
9191
.when((mdc) -> !CollectionUtils.isEmpty(mdc))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.logging.structured;
18+
19+
import org.springframework.boot.context.properties.bind.Binder;
20+
import org.springframework.boot.json.JsonWriter;
21+
import org.springframework.boot.json.JsonWriter.Members;
22+
import org.springframework.core.env.Environment;
23+
import org.springframework.util.StringUtils;
24+
25+
/**
26+
* Properties for Elastic Common Schema structured logging.
27+
*
28+
* @param service service details
29+
* @author Moritz Halbritter
30+
* @author Phillip Webb
31+
* @since 3.4.0
32+
*/
33+
public record ElasticCommonSchemaProperties(Service service) {
34+
35+
static final ElasticCommonSchemaProperties NONE = new ElasticCommonSchemaProperties(Service.NONE);
36+
37+
ElasticCommonSchemaProperties withDefaults(Environment environment) {
38+
Service service = this.service.withDefaults(environment);
39+
return new ElasticCommonSchemaProperties(service);
40+
}
41+
42+
static String withFallbackProperty(Environment environment, String value, String property) {
43+
return (!StringUtils.hasLength(value)) ? environment.getProperty(property) : value;
44+
}
45+
46+
/**
47+
* Add {@link JsonWriter} members for the service.
48+
* @param members the members to add to
49+
*/
50+
public void jsonMembers(JsonWriter.Members<?> members) {
51+
this.service.jsonMembers(members);
52+
}
53+
54+
/**
55+
* Return a new {@link ElasticCommonSchemaProperties} from bound from properties in
56+
* the given {@link Environment}.
57+
* @param environment the source environment
58+
* @return a new {@link ElasticCommonSchemaProperties} instance
59+
*/
60+
public static ElasticCommonSchemaProperties get(Environment environment) {
61+
return Binder.get(environment)
62+
.bind("logging.structured.ecs", ElasticCommonSchemaProperties.class)
63+
.orElse(NONE)
64+
.withDefaults(environment);
65+
}
66+
67+
/**
68+
* Service details.
69+
*
70+
* @param name the application name
71+
* @param version the version of the application
72+
* @param environment the name of the environment the application is running in
73+
* @param nodeName the name of the node the application is running on
74+
*/
75+
public record Service(String name, String version, String environment, String nodeName) {
76+
77+
static final Service NONE = new Service(null, null, null, null);
78+
79+
void jsonMembers(Members<?> members) {
80+
members.add("service.name", this::name).whenHasLength();
81+
members.add("service.version", this::version).whenHasLength();
82+
members.add("service.environment", this::environment).whenHasLength();
83+
members.add("service.node.name", this::nodeName).whenHasLength();
84+
}
85+
86+
Service withDefaults(Environment environment) {
87+
String name = withFallbackProperty(environment, this.name, "spring.application.name");
88+
String version = withFallbackProperty(environment, this.version, "spring.application.version");
89+
return new Service(name, version, this.environment, this.nodeName);
90+
}
91+
92+
}
93+
94+
}

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

Lines changed: 0 additions & 72 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.logging.structured;
18+
19+
import org.springframework.boot.context.properties.bind.Binder;
20+
import org.springframework.boot.json.JsonWriter;
21+
import org.springframework.core.env.Environment;
22+
import org.springframework.util.StringUtils;
23+
24+
/**
25+
* Service details for Graylog Extended Log Format structured logging.
26+
*
27+
* @param host the application name
28+
* @param service the version of the application
29+
* @author Samuel Lissner
30+
* @author Phillip Webb
31+
* @since 3.4.0
32+
*/
33+
public record GraylogExtendedLogFormatProperties(String host, Service service) {
34+
35+
static final GraylogExtendedLogFormatProperties NONE = new GraylogExtendedLogFormatProperties(null, Service.NONE);
36+
37+
GraylogExtendedLogFormatProperties withDefaults(Environment environment) {
38+
String name = withFallbackProperty(environment, this.host, "spring.application.name");
39+
Service service = this.service.withDefaults(environment);
40+
return new GraylogExtendedLogFormatProperties(name, service);
41+
}
42+
43+
static String withFallbackProperty(Environment environment, String value, String property) {
44+
return (!StringUtils.hasLength(value)) ? environment.getProperty(property) : value;
45+
}
46+
47+
/**
48+
* Add {@link JsonWriter} members for the service.
49+
* @param members the members to add to
50+
*/
51+
public void jsonMembers(JsonWriter.Members<?> members) {
52+
members.add("host", this::host).whenHasLength();
53+
this.service.jsonMembers(members);
54+
}
55+
56+
/**
57+
* Return a new {@link GraylogExtendedLogFormatProperties} from bound from properties
58+
* in the given {@link Environment}.
59+
* @param environment the source environment
60+
* @return a new {@link GraylogExtendedLogFormatProperties} instance
61+
*/
62+
public static GraylogExtendedLogFormatProperties get(Environment environment) {
63+
return Binder.get(environment)
64+
.bind("logging.structured.gelf", GraylogExtendedLogFormatProperties.class)
65+
.orElse(NONE)
66+
.withDefaults(environment);
67+
}
68+
69+
/**
70+
* Service details.
71+
*
72+
* @param version the version of the application
73+
*/
74+
public record Service(String version) {
75+
76+
static final Service NONE = new Service(null);
77+
78+
Service withDefaults(Environment environment) {
79+
String version = withFallbackProperty(environment, this.version, "spring.application.version");
80+
return new Service(version);
81+
}
82+
83+
void jsonMembers(JsonWriter.Members<?> members) {
84+
members.add("_service_version", this::version).whenHasLength();
85+
}
86+
87+
}
88+
89+
}

0 commit comments

Comments
 (0)