Logging is an essential aspect of software development, providing valuable insights during application troubleshooting. With the release of Spring Boot 3.4, structured logging in JSON format has been made easier, enabling developers to leverage advanced search and analytics features. This article will guide you through the steps of setting up JSON structured logging in Spring Boot 3.4, along with customizing log formats to fit your application’s needs.
Requirements
To run the examples provided in this article for JSON structured logging with Spring Boot 3.4, you need to meet the following requirements:
- Java version 17 or higher
- Spring Boot 3.4 or newer
Why Structured Logging?
Traditional logging usually outputs logs in a plain text format, which, while readable, can be challenging to analyze systematically. Structured logging solves this by formatting logs in a structured, machine-readable format, typically JSON. This approach makes logs easier to parse, search, and analyze using log management tools, improving overall observability.
Getting Started with JSON Structured Logging
To begin with, create a new Spring Boot project using Spring Boot 3.4 or later. You can generate the project using start.spring.io, ensuring that you select Spring Boot 3.4.0-M2 or newer.
Configuring JSON Logging to the Console
To enable JSON logging in the console, add the following line to your application.properties
file
logging.structured.format.console=ecs
This configuration instructs Spring Boot to use the Elastic Common Schema (ECS) format for logs, which is a standardized format for structured logging. Upon starting your application, you should see log entries formatted in JSON.
Example log output:
{ "@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" }
Logging to a File
If you prefer to keep the console output in a human-readable format and log structured data to a file, modify your application.properties
as follows:
logging.structured.format.file=ecs logging.file.name=log.json
This setup will write structured JSON logs to log.json
while maintaining traditional log output in the console.
Adding Custom Fields to Logs
One of the key advantages of structured logging is the ability to include additional contextual information in your logs. For example, you can add user-specific data such as user IDs to each log entry. This can be achieved using the Mapped Diagnostic Context (MDC).
Here’s a simple example of adding a user ID to a log entry:
@Component class MyLogger implements CommandLineRunner { private static final Logger LOGGER = LoggerFactory.getLogger(MyLogger.class); @Override public void run(String... args) { MDC.put("userId", "1"); LOGGER.info("Hello structured logging!"); MDC.remove("userId"); } }
The resulting log output will include the user ID:
{ "message":"Hello structured logging!", "userId":"1" }
Alternatively, you can use the fluent logging API to achieve the same without relying on MDC:
@Component class MyLogger implements CommandLineRunner { private static final Logger LOGGER = LoggerFactory.getLogger(MyLogger.class); @Override public void run(String... args) { LOGGER.atInfo().setMessage("Hello structured logging!").addKeyValue("userId", "1").log(); } }
Customizing Log Formats
Spring Boot 3.4 not only supports ECS and Logstash formats but also allows developers to define custom log formats. To create a custom log format, implement the StructuredLogFormatter
interface:
class MyStructuredLoggingFormatter implements StructuredLogFormatter<ILoggingEvent> { @Override public String format(ILoggingEvent event) { return "time=" + event.getTimeStamp() + " level=" + event.getLevel() + " message=" + event.getMessage() + "\n"; } }
Once your custom formatter is ready, you can configure Spring Boot to use it by adding the following line to application.properties
:
logging.structured.format.console=com.example.structured_logging_demo.MyStructuredLoggingFormatter
If you prefer to stick with JSON but want more control over the output, Spring Boot 3.4 introduces a new JsonWriter
utility. Here’s how you can use it:
class MyStructuredLoggingFormatter implements StructuredLogFormatter<ILoggingEvent> { private final JsonWriter<ILoggingEvent> writer = JsonWriter.<ILoggingEvent>of((members) -> { members.add("time", (event) -> event.getInstant()); members.add("level", (event) -> event.getLevel()); members.add("thread", (event) -> event.getThreadName()); members.add("message", (event) -> event.getFormattedMessage()); members.add("application").usingMembers((application) -> { application.add("name", "StructuredLoggingDemo"); application.add("version", "1.0.0-SNAPSHOT"); }); members.add("node").usingMembers((node) -> { node.add("hostname", "node-1"); node.add("ip", "10.0.0.7"); }); }).withNewLineAtEnd(); @Override public String format(ILoggingEvent event) { return this.writer.writeToString(event); } }
The resulting log will be a well-structured JSON output:
{ "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"} }
Conclusion
Structured logging in JSON format is a powerful feature that enhances the observability of your Spring Boot applications. With the new capabilities introduced in Spring Boot 3.4, implementing and customizing structured logging has never been easier. Whether you’re using the built-in ECS format or creating your custom format, structured logging is a step forward in making your logs more useful and accessible.
Found the article helpful? if so please follow us on Socials