Gone are the times when developers' jobs ended with the release of the application. Nowadays, developers care more and more about the operational side of IT: perhaps they operate applications themselves, but more probably, their organization fosters increased collaboration between Dev and Ops.
I started to become interested in the Ops side of software when I was still a consultant. When Spring Boot released the Actuator, I became excited. Via its convention-other-configuration nature, it was possible to add monitoring endpoints with just an additional dependency.
Since then, other frameworks have popped up. They also provide monitoring capabilities. In this post, I’d like to compare those frameworks concerning those capabilities.
Spring Boot is the framework that started the trend regarding providing monitoring capabilities. To enable them is only a matter of adding a single dependency known as the Actuator:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>2.4.1</version> </dependency>
The Actuator offers three kinds of endpoints:
- Default endpoints e.g.
- Endpoints contributed by dependencies. For example, adding Flyway will enable the
- Custom endpoints that you can provide
With Spring Boot, one can expose endpoints over JMX and HTTP. For security reasons, by default, JMX is enabled for all endpoints. On the other hand, HTTP is enabled only for
/health (in a condensed form) and
You can secure HTTP endpoints via Spring Security. This allows widespread use-cases. For example, you can enable a specific endpoint but only allow authenticated clients to access it.
Micronaut also offers monitoring endpoints. Those endpoints mostly map to those provided by Spring Boot with a few exceptions.
To add management capabilities, add a single dependency:
<dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-management</artifactId> <version>2.2.2</version> </dependency>
Micronauts expose endpoints over HTTP. To also expose them over JMX, you need to add an extra dependency.
<dependency> <groupId>io.micronaut.jmx</groupId> <artifactId>micronaut-jmx</artifactId> <version>2.1.0</version> </dependency>
By default, all endpoints are enabled, but
Note that the
/metrics endpoint requires a dependency to Micrometer Core.
Last but not least comes Quarkus. Quarkus' approach differs from Spring Boot’s and Micronaut’s: it’s doesn’t implement endpoints itself but relies on a third-party dependency. Before getting to the core, let me digress a bit.
Once upon a time, there was a concept named Java EE and steered by Sun, then by Oracle. The idea was to design a set of specifications and let actors of the industry implement them. This would benefit customers as they could transparently migrate from one Java EE-compatible platform to another. Though the reality was less than ideal, it worked more or less until two things happened.
Java EE platforms were designed when resources were scarce and were to be shared among several applications. The first wrench in the works was the rise of Agile and Cloud, which favored smaller and more efficient runtimes.
The second bump was that Oracle lost interest in Java EE as it didn’t generate enough (any?) revenue. Java EE found a new home at the Eclipse Foundation under the Jakarta EE name, but it didn’t happen overnight - it took about three years. During that time, no technical improvements happened in Java EE.
With the pace of technology, it was a deadly threat. To prevent Jakarta EE from becoming obsolete at the end of the migration period, a new set of specifications known as MicroProfile emerged in parallel. MicroProfile offers a focused set of sub-specifications (the actual version is in brackets):
- Config (2.0)
- Fault Tolerance (3.0)
- Health (3.0)
- JWT RBAC (1.2)
- Metrics (3.0)
- Open API (2.0)
- Open Tracing (2.0)
- Rest Client (2.0)
Interestingly enough, I found at least two Microprofile implementations in the form of libraries - as opposed to a full-fledged application server: SmallRye and Launcher by Fujitsu. Providers of application servers, and developers, can use those dependencies instead of re-implementing the specification themselves. That’s the approach that Quarkus follows.
A specific dependency implements each capability.
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-metrics</artifactId> <version>1.10.5.Final</version> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-health</artifactId> <version>1.10.5.Final</version> </dependency>
Also, Quarkus provides multiple endpoints specific to its CDI implementation (ArC). Because of its focus on Cloud-Native, Quarkus implements compile-time CDI. Hence, it’s able to detect beans that are not used anywhere else and not instantiate them. Note that ArC endpoints are only available in development mode unless explicitly enabled.
When a SmallRye dependency is on the classpath at compile-time, it’s enabled by default. A dedicated flag allows to disable them individually. This is true for other configuration properties, e.g., the path to the endpoint.
Helidon is a framework provided by Oracle based on a sub-set of Jakarta EE APIs and MicroProfile.
I know that it supports
/metrics out-of-the-box. For each of them, you need to add a dependency.
I must admit I didn’t spend enough time to tell more. If you’re interested, please check it by yourself.
Here’s a summary of endpoints for all frameworks.
Application health status
| || |
Logging; allows to change log levels
| || |
Stop the application
| || |
Spring configuration properties
Refresh the application
Entrypoint to ArC-related data