In the previous post, we explored the structure of a Spring Boot application using advanced modular architecture. This time, let’s shift gears to discuss how to enhance observability in Spring Boot microservices and applications. Specifically, we’ll delve into how integrating Micrometer, OpenTelemetry, and the Spring Modulith Starter Insight
can offer comprehensive performance insights across your application’s various layers.
- Prerequisites
- Basic Observability in Spring Boot
- Integrating Advanced Observability Tools
- Running the Application
- Cyclic Dependency Example
- Conclusion
Prerequisites
Before diving into the implementation, make sure you have the following set up:
- Java 21: Ensure Java 21 is installed using SDKMAN.
- Docker & Docker Compose: Required for setting up the local environment.
- Repository Clone: Clone the examples repository to your local environment.
git clone https://github.com/dmakariev/examples.git
cd examples/spring-boot/bookstore
Basic Observability in Spring Boot
A Spring Boot microservice by default exposes limited performance data at the RestController level. While useful, this data is often insufficient for a comprehensive understanding of the interactions between controllers, services, repositories, event publishers, and listeners.
Integrating Advanced Observability Tools
To gain deeper insights, you can enhance observability by integrating the following dependencies:
Spring Modulith Starter Insight
<dependency>
<groupId>org.springframework.modulith</groupId>
<artifactId>spring-modulith-starter-insight</artifactId>
<scope>runtime</scope>
</dependency>
Micrometer Tracing Bridge OpenTelemetry
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
OpenTelemetry Exporter Zipkin
<dependency>
<groupId>org.springframework.modulith</groupId>
<artifactId>spring-modulith-starter-insight</artifactId>
<scope>runtime</scope>
</dependency>
Application Configuration
Update your application.properties
file to enable tracing:
management.tracing.sampling.probability=1.0
management.tracing.enabled=true
management.zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans
After integrating Micrometer, OpenTelemetry, and the Spring Modulith Starter Insight
, the screenshot below shows the detailed performance data captured, including interactions between controllers, services, and other components. This enhanced trace, visualized using Zipkin, highlights the robust observability capabilities now at our disposal.
Running the Application
Start the application with Zipkin enabled
docker compose up --build
Alternatively, you can run only the backend in a separate window
docker compose up --build backend
Cyclic Dependency Example
CyclicDependencyController
We’ve implemented a new CyclicDependencyController
in the com.makariev.examples.spring.bookstore.product
package. This controller introduces a cyclic dependency between the product
and inventory
packages, deliberately triggering modular structure verification errors.
@RestController
@RequestMapping("/api/cycle")
public class CyclicDependencyController {
private final InventoryService inventoryService;
public CyclicDependencyController(InventoryService inventoryService) {
this.inventoryService = inventoryService;
}
@GetMapping
public ResponseEntity<List<Inventory>> getAllInventories() {
final List<Inventory> inventories = inventoryService.findAll();
return ResponseEntity.ok(inventories);
}
}
Modularity Tests
Enable the ModularityTests
class to verify the modular structure
public class ModularityTests {
private final ApplicationModules modules = ApplicationModules.of(BookstoreApplication.class);
@Test
void verifiesModularStructure() {
modules.verify();
}
@Test
void createModuleDocumentation() {
new Documenter(modules).writeDocumentation();
}
}
When these tests are run, you’ll encounter errors due to the cyclic dependency:
[ERROR] Errors:
[ERROR] ModularityTests.verifiesModularStructure:17 » Violations - Cycle detected: Slice inventory ->
...
Conclusion
By adding these observability tools to your Spring Boot microservices or applications, you can obtain valuable performance insights, even across complex structures like those encountered with cyclic dependencies. The Spring Modulith Starter Insight, in particular, offers a modular and flexible approach to structured monitoring, irrespective of the architecture conventions in place.
Be sure to test your application’s modularity with ModularityTests
and leverage the visualized traces provided by Zipkin to fully comprehend interactions across your system’s various layers.
Happy coding!