- Published on
Spring 6 and Spring Boot 3: Observation Api - Part One
- Authors
- Name
- Soufiane Roui
- @sfnroui
Introduction
One of the most important caracterstics of a production grade application, is that is offers you possibility to observe what is going on in terms of memory/cpu usage, components health e.g. databse connection, and functionality. For that matter, Spring Boot 3 introduces Observation API which is part of the micrometer project. The API will help you generate outputs that will be used by developers or third-party software to monitor your application.
Monitoring vs Observability
Observability is about generating outputs from our system which will help us understand the exact root cause of a problem e.g. metrics, logs, and traces. On the other hand, monitoring is about collecting and analyzing data fetched from our system.
Observation API
Observation lifecycle
Let us say, we want to register a user in our system, and we want to make the registration action observable. To do so we can wrap the user registration code in an Observation that will be responsible for making the user registration action observable to a developer or third-party software.
Before jumping into the API, we need to know about the lifecyle of an Observation. Bellow is a diagram that simplifies the lifecyle of an Observation:
Simplified lifecyle of an Observation
An observation can open/close a scope multiple times. Bellow code is a demonstration of the lifecycle phases mentionned above:
ObservationRegistry observationRegistry = ObservationRegistry.create();
Observation observation = Observation.createNotStarted("sample", observationRegistry); // stopped
observation.start(); //started
try (Observation.Scope scope = observation.openScope()) { // scope opened and closed after action execution
System.out.println("Observed Action");
} catch (Exception e) {
observation.error(e); //error
} finally {
observation.stop(); //stopped
}
And bellow code is a simplified version:
ObservationRegistry observationRegistry = ObservationRegistry.create();
Observation observation = Observation.createNotStarted("sample", observationRegistry);
observation.observe(() -> System.out.println("Observed Action"));
Observation, ObservationRegistry, and ObservationHandler
An ObservationRegistry
is responsible for building and storing instances of an Observation
, whereas instances of ObservationHandler
are responsible for handling different lifecycle phases of an Observation
.
You can build an ObservationHandler using bellow code which will expose prometheus metrics:
observationRegistry = ObservationRegistry.create();
meterRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
observationRegistry.observationConfig().observationHandler(new DefaultMeterObservationHandler(meterRegistry));
then, you can use bellow code to create an observation and display created metrics:
Observation observation = Observation.createNotStarted("test", observationRegistry);
observation.observe(() -> log.info("Action performed"));
log.info("Prometheus metrics:\n{}", ((PrometheusMeterRegistry) meterRegistry).scrape());
All above code is included in the github repository observation-api-demo.
See you in the next part!