Structured Logging in Spring Boot 3.4: JSON, ECS, and Custom Formats

Spring Boot 3.4 adds built‑in support for structured logging with ready‑made JSON formats such as Elastic Common Schema, lets you configure console or file outputs, enrich logs via MDC or the fluent API, and enables custom formatters—including a JsonWriter‑based example—for fully tailored, machine‑readable log entries.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Structured Logging in Spring Boot 3.4: JSON, ECS, and Custom Formats

Log recording is a core part of application troubleshooting and system observability. Structured logging outputs logs in a predefined, machine‑readable format (commonly JSON), enabling powerful search, filtering, and analysis.

Spring Boot 3.4 provides out‑of‑the‑box support for structured logging. It includes built‑in formats such as Elastic Common Schema (ECS) and Logstash, and can be extended for custom needs.

Enable Structured Logging on the Console

Add the following property to application.properties to output console logs in ECS format: logging.structured.format.console=ecs When the application starts, logs appear as JSON, e.g.:

{"@timestamp":"2024-07-30T08:41:10.561295200Z","log.level":"INFO","process.pid":67455,"process.thread.name":"main","service.name":"structured-logging-demo","log.logger":"com.example.structured_logging_demo.StructuredLoggingDemoApplication","message":"Started StructuredLoggingDemoApplication in 0.329 seconds (process running for 0.486)","ecs.version":"8.11"}

Write Structured Logs to a File

Configure file output by adding to application.properties:

logging.structured.format.file=ecs<br/>logging.file.name=log.json

The console shows human‑readable logs, while log.json contains the structured JSON entries.

Adding Extra Fields

Use MDC to attach additional data (e.g., userId) to each log event:

@Component<br/>class MyLogger implements CommandLineRunner {<br/>    private static final Logger LOGGER = LoggerFactory.getLogger(MyLogger.class);<br/><br/>    @Override<br/>    public void run(String... args) {<br/>        MDC.put("userId", "1");<br/>        LOGGER.info("Hello structured logging!");<br/>        MDC.remove("userId");<br/>    }<br/>}

The resulting JSON includes the extra field:

{..., "message":"Hello structured logging!", "userId":"1", ...}

Alternatively, use the fluent API without MDC:

@Component<br/>class MyLogger implements CommandLineRunner {<br/>    private static final Logger LOGGER = LoggerFactory.getLogger(MyLogger.class);<br/><br/>    @Override<br/>    public void run(String... args) {<br/>        LOGGER.atInfo().setMessage("Hello structured logging!")<br/>              .addKeyValue("userId", "1")<br/>              .log();<br/>    }<br/>}

Custom Log Formatter

Create a class implementing StructuredLogFormatter<ILoggingEvent> and register it in application.properties:

class MyStructuredLoggingFormatter implements StructuredLogFormatter<ILoggingEvent> {<br/>    @Override<br/>    public String format(ILoggingEvent event) {<br/>        return "time=" + event.getTimeStamp() + " level=" + event.getLevel() + " message=" + event.getMessage() + "
";<br/>    }<br/>}
logging.structured.format.console=com.example.structured_logging_demo.MyStructuredLoggingFormatter

Running the app now prints logs like:

time=1722330118045 level=INFO message=Hello structured logging!

For JSON output, Spring Boot 3.4 introduces JsonWriter:

class MyStructuredLoggingFormatter implements StructuredLogFormatter<ILoggingEvent> {<br/>    private final JsonWriter<ILoggingEvent> writer = JsonWriter.<ILoggingEvent>of(members -> {<br/>        members.add("time", e -> e.getInstant());<br/>        members.add("level", e -> e.getLevel());<br/>        members.add("thread", e -> e.getThreadName());<br/>        members.add("message", e -> e.getFormattedMessage());<br/>        members.add("application").usingMembers(app -> {<br/>            app.add("name", "StructuredLoggingDemo");<br/>            app.add("version", "1.0.0-SNAPSHOT");<br/>        });<br/>        members.add("node").usingMembers(node -> {<br/>            node.add("hostname", "node-1");<br/>            node.add("ip", "10.0.0.7");<br/>        });<br/>    }).withNewLineAtEnd();<br/><br/>    @Override<br/>    public String format(ILoggingEvent event) {<br/>        return writer.writeToString(event);<br/>    }<br/>}
logging.structured.format.console=com.example.structured_logging_demo.MyStructuredLoggingFormatter

The generated log looks like:

{"time":"2024-07-30T09:14:49.377308361Z","level":"INFO","thread":"main","message":"Hello structured logging!","application":{"name":"StructuredLoggingDemo","version":"1.0.0-SNAPSHOT"},"node":{"hostname":"node-1","ip":"10.0.0.7"}}

Note: Spring Boot 3.0/3.1 lifecycle has ended; upgrade to the latest version.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaJSONloggingSpring BootECSstructured logging
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.