This episode covers observability in Quarkus: SmallRye Health for liveness and readiness probes, SmallRye Metrics and Micrometer, logging and structured logging configuration, as well as creating custom health checks.

An application running in production without observability is like flying without instruments. You don't know whether the application is healthy, slow, or refusing connections — until users complain. Observability answers three basic questions: is the application alive, is it ready to receive traffic, and how well is it performing.
Episode 9 covers the foundations of Quarkus observability: SmallRye Health for liveness and readiness probes, SmallRye Metrics and Micrometer for measurements, logging and structured logging configuration, as well as creating custom health checks.
SmallRye Health implements the MicroProfile Health specification. Add it with ./mvnw quarkus:add-extension -Dextensions=smallrye-health.
Once the extension is active, three endpoints are available:
/q/health # combined liveness + readiness
/q/health/live # liveness probe
/q/health/ready # readiness probecurl http://localhost:8080/q/healthThe response is JSON-formatted:
{
"status": "UP",
"checks": [
{
"name": "SmallRye Reactive Messaging - liveness check",
"status": "UP"
}
]
}The command curl http://localhost:8080/q/health returns the aggregate status. Kubernetes uses /q/health/live for the liveness probe and /q/health/ready for the readiness probe.
Liveness answers: is the application process still alive and not deadlocked? Implement the HealthCheck interface:
import io.smallrye.health.api.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Liveness;
import jakarta.enterprise.context.ApplicationScoped;
@Liveness
@ApplicationScoped
public class LivenessCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("aplikasi-hidup");
}
}The call() method returns HealthCheckResponse.up("aplikasi-hidup") when healthy. The @Liveness annotation marks this check as part of the liveness probe.
Readiness answers: is the application ready to receive traffic? Implement HealthCheck with the @Readiness annotation, then return HealthCheckResponse.up("database") when dependencies like the database are ready and down when there's a problem. Kubernetes stops sending traffic to a pod whose readiness is down, while liveness remains up as long as the process is alive so the pod isn't restarted needlessly.
Quarkus supports two metrics APIs: SmallRye Metrics (MicroProfile) and Micrometer. Micrometer is the modern choice that integrates with many backends; add it with ./mvnw quarkus:add-extension -Dextensions=micrometer-registry-prometheus.
With Micrometer + the Prometheus registry, metrics are available at /q/metrics in Prometheus format:
curl http://localhost:8080/q/metrics
curl http://localhost:8080/q/metrics | grep quarkusMeasure business behavior with MeterRegistry:
import io.micrometer.core.instrument.MeterRegistry;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
@ApplicationScoped
public class OrderService {
@Inject
MeterRegistry registry;
public void buatOrder() {
registry.counter("orders.created").increment();
}
}registry.counter("orders.created").increment() increments the counter each time an order is created. This metric appears at /q/metrics and can be pulled by Prometheus for alerting.
Configure the log level per category:
quarkus.log.level=INFO
quarkus.log.category."com.example".level=DEBUG
quarkus.log.console.enable=trueFor production, JSON-formatted logs are easy for aggregators to process:
quarkus.log.console.format-json=true
quarkus.log.console.json-export-name=applicationWith format-json=true, every log line becomes a JSON object containing the timestamp, level, logger, and message. This makes automated parsing and querying of logs in centralized systems much easier.
From code, use org.jboss.logging.Logger with the pattern LOG.info("Order baru dibuat") and LOG.debugf("Detail order: %s", id). These structured logs follow the global configuration.
The combination of health probes and metrics is the foundation of monitoring. In a Kubernetes deployment, configure livenessProbe with the path /q/health/live and readinessProbe with the path /q/health/ready, both on port 8080. Kubernetes restarts pods that fail liveness and stops traffic to pods that fail readiness; the metrics from /q/metrics are scraped by Prometheus for alerting and dashboards.
Episode 9 makes your application clearly visible from the outside: understanding SmallRye Health with liveness and readiness probes, creating custom health checks, using SmallRye Metrics and Micrometer for custom metrics, and configuring structured logging for production.
Key takeaways:
/q/health, /q/health/live, and /q/health/ready are provided by SmallRye Health.HealthCheck interface./q/metrics.In episode 10 we'll cover advanced transactions and persistence — transaction management with Narayana/JTA, propagation behavior and rollback, JPA optimization, fetch strategies and caching, as well as database migrations with Flyway or Liquibase.