diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml
index 2602003e187d..387c4c4ed68f 100644
--- a/spring-boot-modules/pom.xml
+++ b/spring-boot-modules/pom.xml
@@ -103,6 +103,7 @@
spring-boot-3-test-pitfalls
spring-boot-3-testcontainers
spring-boot-3-2
+ spring-boot-3-4
spring-boot-resilience4j
spring-boot-properties
spring-boot-properties-2
diff --git a/spring-boot-modules/spring-boot-3-4/README.md b/spring-boot-modules/spring-boot-3-4/README.md
new file mode 100644
index 000000000000..5616cce48b45
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-4/README.md
@@ -0,0 +1 @@
+## Relevant Articles
diff --git a/spring-boot-modules/spring-boot-3-4/log.json b/spring-boot-modules/spring-boot-3-4/log.json
new file mode 100644
index 000000000000..44dc478934a5
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-4/log.json
@@ -0,0 +1,69 @@
+{
+ "@timestamp": "2024-12-19T10:34:02.220152180Z",
+ "log.level": "INFO",
+ "process.pid": 34696,
+ "process.thread.name": "main",
+ "service.name": "BaeldungService",
+ "service.version": "1",
+ "service.environment": "Production",
+ "service.node.name": "Primary",
+ "log.logger": "com.baeldung.springstructuredlogging.StructuredLoggingApp",
+ "message": "Starting StructuredLoggingApp using Java 23 with PID 34696 (\/home\/michael\/tutorials\/spring-boot-modules\/spring-boot-3-4\/target\/classes started by michael in \/home\/michael\/tutorials\/spring-boot-modules\/spring-boot-3-4)",
+ "ecs.version": "8.11"
+}
+{
+ "@timestamp": "2024-12-19T10:34:02.240898973Z",
+ "log.level": "INFO",
+ "process.pid": 34696,
+ "process.thread.name": "main",
+ "service.name": "BaeldungService",
+ "service.version": "1",
+ "service.environment": "Production",
+ "service.node.name": "Primary",
+ "log.logger": "com.baeldung.springstructuredlogging.StructuredLoggingApp",
+ "message": "No active profile set, falling back to 1 default profile: \"default\"",
+ "ecs.version": "8.11"
+}
+{
+ "@timestamp": "2024-12-19T10:34:03.558243665Z",
+ "log.level": "INFO",
+ "process.pid": 34696,
+ "process.thread.name": "main",
+ "service.name": "BaeldungService",
+ "service.version": "1",
+ "service.environment": "Production",
+ "service.node.name": "Primary",
+ "log.logger": "com.baeldung.springstructuredlogging.StructuredLoggingApp",
+ "message": "Started StructuredLoggingApp in 2.777 seconds (process running for 4.356)",
+ "ecs.version": "8.11"
+}
+{
+ "@timestamp": "2024-12-19T10:34:03.564752429Z",
+ "log.level": "INFO",
+ "process.pid": 34696,
+ "process.thread.name": "main",
+ "service.name": "BaeldungService",
+ "service.version": "1",
+ "service.environment": "Production",
+ "service.node.name": "Primary",
+ "log.logger": "com.baeldung.springstructuredlogging.CustomLog",
+ "message": "Hello structured logging!",
+ "userName": "Baeldung",
+ "userId": "1",
+ "ecs.version": "8.11"
+}
+{
+ "@timestamp": "2024-12-19T10:34:03.568047793Z",
+ "log.level": "INFO",
+ "process.pid": 34696,
+ "process.thread.name": "main",
+ "service.name": "BaeldungService",
+ "service.version": "1",
+ "service.environment": "Production",
+ "service.node.name": "Primary",
+ "log.logger": "com.baeldung.springstructuredlogging.CustomLog",
+ "message": "Hello Structure logging!",
+ "userId": "1",
+ "userName": "Baeldung",
+ "ecs.version": "8.11"
+}
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-4/pom.xml b/spring-boot-modules/spring-boot-3-4/pom.xml
new file mode 100644
index 000000000000..542a7eb03edd
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-4/pom.xml
@@ -0,0 +1,27 @@
+
+ 4.0.0
+ com.baeldung.spring-boot-3-4
+ spring-boot-3-4
+ 1.0.0-SNAPSHOT
+ spring-boot-3-4
+
+
+ org.springframework.boot
+ spring-boot-starter
+ ${spring-boot.version}
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+ 3.4.0
+
+
diff --git a/spring-boot-modules/spring-boot-3-4/src/main/java/com/baeldung/springstructuredlogging/CustomLog.java b/spring-boot-modules/spring-boot-3-4/src/main/java/com/baeldung/springstructuredlogging/CustomLog.java
new file mode 100644
index 000000000000..0cff4e9366a1
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-4/src/main/java/com/baeldung/springstructuredlogging/CustomLog.java
@@ -0,0 +1,34 @@
+package com.baeldung.springstructuredlogging;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CustomLog implements CommandLineRunner {
+ private static final Logger LOGGER = LoggerFactory.getLogger(CustomLog.class);
+
+ public void additionalDetailsWithMdc() {
+ MDC.put("userId", "1");
+ MDC.put("userName", "Baeldung");
+ LOGGER.info("Hello structured logging!");
+ MDC.remove("userId");
+ MDC.remove("userName");
+ }
+
+ public void additionalDetailsUsingFluentApi() {
+ LOGGER.atInfo()
+ .setMessage("Hello Structure logging!")
+ .addKeyValue("userId", "1")
+ .addKeyValue("userName", "Baeldung")
+ .log();
+ }
+
+ @Override
+ public void run(String... args) {
+ additionalDetailsWithMdc();
+ additionalDetailsUsingFluentApi();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-4/src/main/java/com/baeldung/springstructuredlogging/MyStructuredLoggingFormatter.java b/spring-boot-modules/spring-boot-3-4/src/main/java/com/baeldung/springstructuredlogging/MyStructuredLoggingFormatter.java
new file mode 100644
index 000000000000..df5aa8f24c5d
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-4/src/main/java/com/baeldung/springstructuredlogging/MyStructuredLoggingFormatter.java
@@ -0,0 +1,28 @@
+package com.baeldung.springstructuredlogging;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import org.springframework.boot.json.JsonWriter;
+import org.springframework.boot.logging.structured.StructuredLogFormatter;
+
+public class MyStructuredLoggingFormatter implements StructuredLogFormatter {
+
+ private final JsonWriter writer = JsonWriter.of((members) -> {
+ members.add("time", ILoggingEvent::getInstant);
+ members.add("level", ILoggingEvent::getLevel);
+ members.add("thread", ILoggingEvent::getThreadName);
+ members.add("message", ILoggingEvent::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);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-4/src/main/java/com/baeldung/springstructuredlogging/StructuredLoggingApp.java b/spring-boot-modules/spring-boot-3-4/src/main/java/com/baeldung/springstructuredlogging/StructuredLoggingApp.java
new file mode 100644
index 000000000000..d397488e88f4
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-4/src/main/java/com/baeldung/springstructuredlogging/StructuredLoggingApp.java
@@ -0,0 +1,13 @@
+package com.baeldung.springstructuredlogging;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class StructuredLoggingApp {
+
+ public static void main(String[] args) {
+ SpringApplication.run(StructuredLoggingApp.class, args);
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-3-4/src/main/resources/application.properties b/spring-boot-modules/spring-boot-3-4/src/main/resources/application.properties
new file mode 100644
index 000000000000..af4e1a3d0b69
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-4/src/main/resources/application.properties
@@ -0,0 +1,6 @@
+logging.structured.format.file=ecs
+logging.file.name=log.json
+logging.structured.ecs.service.name=BaeldungService
+logging.structured.ecs.service.version=1
+logging.structured.ecs.service.environment=Production
+logging.structured.ecs.service.node-name=Primary
\ No newline at end of file