Learn Quarkus - Observability & Health
Episode 9 of 24

Learn Quarkus - Observability & Health

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.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

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.

Quarkus SmallRye Health for Probes

Adding the Extension

SmallRye Health implements the MicroProfile Health specification. Add it with ./mvnw quarkus:add-extension -Dextensions=smallrye-health.

Health Endpoints

Once the extension is active, three endpoints are available:

Quarkus health endpoints
/q/health       # combined liveness + readiness
/q/health/live  # liveness probe
/q/health/ready # readiness probe
Checking the health endpoint
curl http://localhost:8080/q/health

The response is JSON-formatted:

Health check response
{
  "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.

Custom Health Checks

Liveness Checks

Liveness answers: is the application process still alive and not deadlocked? Implement the HealthCheck interface:

JavaCustom liveness check
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 Checks

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.

SmallRye Metrics and Micrometer Integration

Adding the Extension

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.

Metrics Endpoint

With Micrometer + the Prometheus registry, metrics are available at /q/metrics in Prometheus format:

Reading application metrics
curl http://localhost:8080/q/metrics
curl http://localhost:8080/q/metrics | grep quarkus

Custom Metrics

Measure business behavior with MeterRegistry:

JavaCustom metric counter
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.

Logging and Structured Logging

Logging Configuration

Configure the log level per category:

Logging configuration
quarkus.log.level=INFO
quarkus.log.category."com.example".level=DEBUG
quarkus.log.console.enable=true

Structured JSON Logging

For production, JSON-formatted logs are easy for aggregators to process:

JSON logging
quarkus.log.console.format-json=true
quarkus.log.console.json-export-name=application

With 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.

Logging from Code

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.

Monitoring and Integration

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.

Wrap-Up

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.
  • Liveness indicates a live process; readiness indicates readiness to receive traffic.
  • Custom checks are created with the HealthCheck interface.
  • Micrometer + Prometheus exposes metrics at /q/metrics.
  • Custom counters and timers add visibility into business behavior.
  • Structured JSON logging makes centralized log aggregation easier.

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.