-
Notifications
You must be signed in to change notification settings - Fork 41.3k
Closed
Description
The new structured logging support is great and provides all the necessary building blocks to create custom JSON log formats via JsonWriterStructuredLogFormatter.
However, JsonValueWriter.writeString() escapes /
as \/
in JSON, which causes issues when targeting platforms like Google Cloud Logging. GCP expects specific root-level keys such as:
{
"logging.googleapis.com/spanId": "abc",
"logging.googleapis.com/trace": "projects/my-project/traces/123"
}
But the current implementation renders them as:
{
"logging.googleapis.com\/spanId": "abc",
"logging.googleapis.com\/trace": "projects\/my-project\/traces\/123"
}
example impl
public class GCPStructuredLogFormatter extends JsonWriterStructuredLogFormatter<ILoggingEvent> {
GCPStructuredLogFormatter(StackTracePrinter stackTracePrinter,
ContextPairs contextPairs,
ThrowableProxyConverter throwableProxyConverter,
StructuredLoggingJsonMembersCustomizer<?> customizer) {
super(GCPStructuredLogFormatter::jsonMembers, customizer);
}
private static void jsonMembers(JsonWriter.Members<ILoggingEvent> members) {
members.add("timestamp", ILoggingEvent::getInstant).as(GCPStructuredLogFormatter::asTimestamp);
members.add("message", ILoggingEvent::getFormattedMessage);
members.add("logger_name", ILoggingEvent::getLoggerName);
members.add("thread_name", ILoggingEvent::getThreadName);
members.add("level", ILoggingEvent::getLevel);
members.add("logging.googleapis.com/spanId", (e) -> "abc");
members.add("logging.googleapis.com/trace", (e) -> "projects/my-project/traces/123");
}
private static String asTimestamp(Instant instant) {
OffsetDateTime offsetDateTime = OffsetDateTime.ofInstant(instant, ZoneId.systemDefault());
return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(offsetDateTime);
}
}
This prevents GCP from recognizing the structured fields.
Request: Add a way to opt out of escaping /
in JSON keys when using structured logging.
This would avoid having to reimplement JSON rendering logic entirely and allow users to fully benefit from the structured logging infrastructure provided by Spring Boot.
Metadata
Metadata
Assignees
Labels
type: bugA general bugA general bug
Type
Projects
Relationships
Development
Select code repository
Activity
mhalbritter commentedon Jun 16, 2025
I wonder why we escape
/
in the first place. The RFC reads:And a string is:
nosan commentedon Jun 16, 2025
Looks like only Spring Boot escapes
/
, other JSON libraries don't do that.mhalbritter commentedon Jun 16, 2025
Thanks for testing, @nosan. I think we stop escaping the
/
. @philwebb do you agree?[-]Allow unescaped forward slash in JSON keys for structured logging[/-][+]Allow unescaped forward slash in JSON for structured logging[/+]philwebb commentedon Jun 17, 2025
Yes, I think this is a bug if we don't align with the other libraries.
[-]Allow unescaped forward slash in JSON for structured logging[/-][+]JSON writer incorrectly escapes forward slash which can cause structure logging issues[/+]Stop escaping forward slash when writing JSON