skip to content

Structured / JSON Logging

Structured logging emits JSON in ECS, Logstash or GELF format so an aggregator can index fields instead of parsing text. Interviewers ask because searching by field is the difference between five seconds and an hour during an incident.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

How do you turn on JSON structured logging in Spring Boot 3.4, and why would you want it?

level: juniorimportance: must knowfreq 55%

answer

  1. logging.structured.format.console = ecs / logstash / gelf
  2. separate console vs file property
  3. Boot 3.4 native, no extra dependency
  4. JSON replaces the pattern
  5. for log shippers / aggregators

basics

~10 s

Set logging.structured.format.console=ecs (or logstash/gelf) in application.properties. Boot then prints each log line as one JSON object instead of plain text, so log aggregators like Elasticsearch or Loki can parse fields automatically.

solid answer

~40 s

Spring Boot 3.4 added native structured logging. Set `logging.structured.format.console=ecs` (or `logstash`/`gelf`) to make the console appender emit one JSON object per event; use `logging.structured.format.file` for the log file, and you can pick different formats for each. Once enabled, Boot replaces the default human-readable pattern with JSON, so every log line carries typed fields (timestamp, level, logger, message, MDC, stack trace) that a shipper like Filebeat, Fluent Bit, or Promtail can ingest without regex grok parsing. This matters in containerized/cloud environments where logs go to stdout and are collected centrally — structured fields make them queryable and correlatable. No extra dependency is needed; it works with the default Logback (and with Log4j2).

code

java · 18 lines
java
// application.properties
// Emit ECS JSON on stdout (collected by Filebeat/Fluent Bit in containers):
//   logging.structured.format.console=ecs
// Keep a readable console locally but write JSON to the log file:
//   logging.structured.format.file=ecs
//   logging.file.name=app.log

// Nothing changes in application code -- you still log normally:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OrderService {
    private static final Logger log = LoggerFactory.getLogger(OrderService.class);

    public void place(long id) {
        log.info("Order {} placed", id); // rendered as a JSON object when structured logging is on
    }
}

go deeper

for a junior

Know the property name and that it produces JSON per line for aggregators.

for a middle

Know console vs file are separate settings and that the pattern is replaced.

for a senior

Explain why (grok-free ingestion), profile-gating, and stdout-collection in containers.

for a principal

Frame it as part of an observability pipeline: field taxonomy, cost of grok parsing, correlation.

**Structured logging** means each log record is emitted as a machine-parseable object (almost always JSON) with named fields, instead of a single human-readable string. A traditional line like `2026-07-22 10:00:00.123 INFO 12345 --- [main] c.e.MyService : Order 42 placed` forces the log pipeline to regex-parse ("grok") the fields back out. A structured line like `{"@timestamp":"...","log.level":"INFO","message":"Order 42 placed","log.logger":"c.e.MyService"}` is already parsed — the aggregator just indexes the fields. **Before Spring Boot 3.4** you achieved this with a third-party encoder, typically `net.logstash.logback:logstash-logback-encoder`, wired through a `logback-spring.xml`. **Spring Boot 3.4 added first-class support** so you no longer need that dependency or XML for the common cases. **How to enable it:** - `logging.structured.format.console=ecs` — makes the *console* (stdout) appender emit JSON. - `logging.structured.format.file=ecs` — makes the *file* appender emit JSON (requires `logging.file.name` or `logging.file.path` to actually write a file). - The two are independent: a common setup is JSON on the file for shipping and the normal readable pattern on the console for local dev (or vice-versa in containers where stdout is the collected stream). **Built-in format values:** `ecs` (Elastic Common Schema), `logstash` (Logstash JSON), and `gelf` (Graylog Extended Log Format). You can also pass the fully-qualified class name of a custom `StructuredLogFormatter`. **What Boot does under the hood:** enabling a structured format swaps the appender's encoder for a `StructuredLogEncoder` (Logback) / structured layout (Log4j2). The normal `logging.pattern.console` is ignored for that appender because a pattern and JSON are mutually exclusive. Fields emitted include the timestamp, level, logger name, thread, message, everything in the **MDC** (Mapped Diagnostic Context), any key-value pairs, and — critically — the exception/stack trace rendered into the format's error fields (e.g. ECS's `error.type`, `error.message`, `error.stack_trace`). **When to use it:** any environment where logs are collected centrally — Kubernetes, Docker/Railway, ECS/EKS, or any host running Filebeat/Fluent Bit/Fluentd/Promtail/Vector. In pure local development the plain pattern is more readable, which is exactly why the console and file formats are configured separately. **Gotchas:** (1) JSON is one object per line (newline-delimited JSON) — do not pretty-print. (2) The default readable console goes away once you set the console format, which can surprise developers running locally, so many teams only set the *file* format or gate it behind a `prod` profile. (3) It works with the default Logback; you do not add `logstash-logback-encoder` for the built-in formats.

  • If you set only `logging.structured.format.console`, what happens to `logging.pattern.console`?
    It's effectively ignored for that appender — a JSON structured format and a text pattern are mutually exclusive, so the console emits JSON, not the pattern.
  • Do you need to add the logstash-logback-encoder dependency to use the built-in formats?
    No. The `ecs`, `logstash`, and `gelf` values are built into Spring Boot 3.4 and work with the default Logback. You'd only add that encoder for pre-3.4 setups or very custom needs.

saying these in an interview costs you the question

  • Thinking structured logging requires manually writing a logback-spring.xml in Boot 3.4
  • Assuming one property enables JSON everywhere (console and file share one setting)
  • Claiming you must add an external dependency for the built-in formats

context

open as a page

How do you enrich structured logs in Spring Boot 3.4 with custom fields (like traceId or a service name) without writing a full custom formatter?

level: middleimportance: should knowfreq 35%

basics

~10 s

Put per-request values in SLF4J's MDC — they appear as fields automatically. Use logging.structured.json.add/.rename/.exclude to shape static fields, and the format's service properties (e.g. logging.structured.ecs.service.name) for service metadata.

open as a page

Compare the three built-in structured logging formats in Spring Boot 3.4 (ecs, logstash, gelf). When would you pick each?

level: middleimportance: should knowfreq 40%

basics

~20 s

ecs = Elastic Common Schema (for Elasticsearch/Kibana), logstash = the Logstash JSON layout, gelf = Graylog Extended Log Format (for Graylog). Pick the one your log backend understands natively so fields map without extra transformation.

open as a page

How do you implement and register a custom structured logging format in Spring Boot 3.4 when none of the built-in ones fit?

level: seniorimportance: should knowfreq 30%

basics

~10 s

Implement org.springframework.boot.logging.structured.StructuredLogFormatter<E> (E is the log-framework event type, e.g. Logback's ILoggingEvent), return a JSON string from format(event), then set logging.structured.format.console (or .file) to that class's fully-qualified name.

open as a page

Compare Boot 3.4 native structured logging with the encoder-based approach (logstash-logback-encoder). How would you architect JSON logging for an aggregation pipeline across many services?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

Boot 3.4 native structured logging gives JSON via one property with no XML or extra dependency, covering ecs/logstash/gelf. The encoder approach (logstash-logback-encoder in logback-spring.xml) is more configurable but heavier. Prefer native; drop to the encoder only for needs native can't express.

open as a page