How do you turn on JSON structured logging in Spring Boot 3.4, and why would you want it?
answer
- logging.structured.format.console = ecs / logstash / gelf
- separate console vs file property
- Boot 3.4 native, no extra dependency
- JSON replaces the pattern
- for log shippers / aggregators
basics
~10 sSet 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 sSpring 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// 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
Know the property name and that it produces JSON per line for aggregators.
Know console vs file are separate settings and that the pattern is replaced.
Explain why (grok-free ingestion), profile-gating, and stdout-collection in containers.
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