Backend Development 8 min read

Master Structured Logging in Spring Boot 3.4 with ECS and Custom Formats

This guide explains why structured logging is essential for observability, shows how Spring Boot 3.4 adds out‑of‑the‑box support for Elastic Common Schema and Logstash formats, and provides step‑by‑step configurations and code examples for console output, file logging, custom fields, and custom formatters.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Structured Logging in Spring Boot 3.4 with ECS and Custom Formats

Logging is a cornerstone of troubleshooting and observability, alongside metrics and tracing. Structured logging writes logs in a well‑defined, machine‑readable format—most commonly JSON—so they can be ingested by log management systems for powerful search and analysis.

Spring Boot 3.4 introduces built‑in support for structured logging, offering two ready‑made formats: Elastic Common Schema (ECS) and Logstash . Developers can also extend the system with custom formats.

1. Quick Start

Because the 3.4 release is still a milestone (3.4.0‑M3), you need to use the milestone repository to fetch the parent pom:

<code>&lt;parent&gt;
  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
  &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
  &lt;version&gt;3.4.0-M3&lt;/version&gt;
  &lt;relativePath/&gt;
&lt;/parent&gt;</code>

Configure the logger to use the ECS format for console output:

<code>logging:
  structured:
    format:
      console: ecs</code>

The console will now emit JSON‑formatted logs.

2. Writing to a File

To keep human‑readable logs on the console while writing structured JSON logs to a file, add the following configuration and disable the default console ECS formatter:

<code>logging:
  file:
    name: json.log
  structured:
    format:
      file: ecs</code>

This creates json.log in the project root with the same JSON structure as the console output.

3. Adding Custom Fields

Using MDC (Mapped Diagnostic Context) you can inject additional data, such as a user ID, into each log event:

<code>@Component
public class PackCustomLogger implements CommandLineRunner {
  private static final Logger LOGGER = LoggerFactory.getLogger(PackCustomLogger.class);

  @Override
  public void run(String... args) {
    MDC.put("userId", "666");
    LOGGER.info("Hello structured logging, custom field!");
    MDC.remove("userId");
  }
}</code>

The resulting JSON contains a userId field.

Alternatively, the fluent API can add fields without MDC:

<code>LOGGER.atInfo()
      .setMessage("Hello structured logging, by fluent!")
      .addKeyValue("userId", "888")
      .log();</code>

4. Enriching Logs with Service Metadata

ECS defines standard fields for service name, version, environment, and node name. Set them in application.yml :

<code>logging:
  structured:
    ecs:
      service:
        name: my-app
        version: 1.0.0
        node-name: app-node-01</code>

The generated JSON now includes service.name , service.version , and service.node.name , which can be filtered in Elasticsearch/Kibana.

5. Custom StructuredLogFormatter

To define a completely custom JSON structure, implement the StructuredLogFormatter interface:

<code>public class PackStructuredLoggingFormatter implements StructuredLogFormatter&lt;ILoggingEvent&gt; {
  private final JsonWriter&lt;ILoggingEvent&gt; writer = JsonWriter.&lt;ILoggingEvent&gt;of(members -> {
    members.add("time", e -> DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
        .format(e.getInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()));
    members.add("level", ILoggingEvent::getLevel);
    members.add("thread", ILoggingEvent::getThreadName);
    members.add("message", ILoggingEvent::getFormattedMessage);
    members.add("application").usingMembers(app -> {
      app.add("name", "StructuredLoggingDemo");
      app.add("version", "1.0.0-SNAPSHOT");
    });
    members.add("node").usingMembers(node -> {
      node.add("hostname", "pack-node-1");
      node.add("ip", "127.0.0.1");
    });
  }).withNewLineAtEnd();

  @Override
  public String format(ILoggingEvent event) {
    return writer.writeToString(event);
  }
}</code>

Reference the formatter in the configuration:

<code>logging:
  structured:
    format:
      console: com.pack.PackStructuredLoggingFormatter</code>

The console now prints JSON that includes the custom application and node objects.

Conclusion

Spring Boot’s built‑in structured logging makes it straightforward to emit JSON logs compatible with Elasticsearch, enabling powerful filtering and visualization through Kibana.

JavaJSONSpring Bootstructured loggingLogstashElastic Common Schema
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login 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.