Skip to content

Spring Boot Production Monitoring and Distributed Tracing

Monitoring Spring Boot Applications in Production

Section titled “Monitoring Spring Boot Applications in Production”

In production, monitoring is typically done using multiple tools that collect metrics, logs, health checks, and traces.

flowchart TD
    A[Spring Boot Application] --> B[Spring Boot Actuator]
    B --> C[Micrometer]
    C --> D[Prometheus]
    D --> E[Grafana]
Component Purpose
Spring Boot Actuator Exposes health and metrics endpoints
Micrometer Metrics collection library
Prometheus Scrapes and stores metrics
Grafana Dashboard visualization
ELK Stack Centralized log aggregation and analysis
Distributed Tracing (Sleuth + Zipkin/Jaeger) End-to-end request tracing
  • CPU usage
  • Memory usage
  • JVM threads
  • HTTP request count
  • Error rate
  • Database connection pool usage
  • Response time
/actuator/health
/actuator/metrics
/actuator/prometheus
/actuator/env
/actuator/threaddump
/actuator/httptrace
/actuator/beans
/actuator/loggers

Example:

http://localhost:8080/actuator/health

Response:

{
"status": "UP"
}

Spring Boot uses Micrometer as its metrics facade.

flowchart TD
    A[Application Code] --> B[Micrometer]
    B --> C[MeterRegistry]
    C --> D[Prometheus / Datadog / New Relic]
Component Description
Micrometer Metrics collection library
MeterRegistry Stores and publishes metrics
Meter Individual metric
Tags Metadata used to classify metrics
Type Example
Counter Number of requests
Gauge Current memory usage
Timer API response time
Distribution Summary Payload size

Example:

Counter requestCounter = meterRegistry.counter("api.requests");
requestCounter.increment();

Built-in metrics include JVM, memory, thread, HTTP request, and database connection pool metrics.

Metrics endpoint:

/actuator/metrics

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
management:
endpoints:
web:
exposure:
include: "*"
metrics:
export:
prometheus:
enabled: true

Prometheus scrapes:

http://localhost:8080/actuator/prometheus

Configuration:

scrape_configs:
- job_name: springboot
metrics_path: /actuator/prometheus
static_configs:
- targets:
- localhost:8080

Configure Prometheus as a data source and build dashboards for:

  • JVM memory
  • HTTP latency
  • Request rate
  • Error percentage

Example query:

rate(http_server_requests_seconds_count[1m])

Distributed tracing follows a request across multiple microservices.

Example architecture:

flowchart LR
    Client --> Gateway
    Gateway --> Order
    Order --> Payment
    Payment --> Inventory

Example trace timing:

Trace ID: 12345
Order Service -> 50ms
Payment Service -> 200ms
Inventory Service -> 40ms
Term Meaning
Trace Complete request journey
Span Single operation within a trace
Trace ID Unique identifier for the entire request
Span ID Unique identifier for one operation

Common tools:

  • Zipkin
  • Jaeger
  • OpenTelemetry

Note: Spring Cloud Sleuth is in maintenance mode as of Spring Boot 3 / Spring Cloud 2022+, superseded by Micrometer Tracing (paired with an exporter like OpenTelemetry or Zipkin’s Brave). The concepts below (TraceId/SpanId generation and propagation) still apply — only the library implementing them has changed. New Spring Boot 3.x projects should reach for Micrometer Tracing instead of adding Sleuth.

Spring Cloud Sleuth automatically generates and propagates tracing information.

flowchart TD
    A[Client Request] --> B[Spring Cloud Sleuth]
    B --> C[Generate TraceId & SpanId]
    C --> D[Propagate to Downstream Services]

Example log:

[OrderService, traceId=12345, spanId=abcd]
Processing order

Sleuth propagates headers such as:

X-B3-TraceId
X-B3-SpanId
X-B3-ParentSpanId

Dependency:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

Optional:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

Typical flow:

sequenceDiagram
    participant C as Client
    participant G as Gateway
    participant O as Order Service
    participant P as Payment Service
    participant I as Inventory Service

    C->>G: HTTP Request
    G->>O: TraceId=12345
    O->>P: TraceId=12345
    P->>I: TraceId=12345

Each service creates its own span while sharing the same TraceId.

Example:

Gateway: TraceId=12345 SpanId=A1
Order: TraceId=12345 SpanId=B1
Payment: TraceId=12345 SpanId=C1
Inventory: TraceId=12345 SpanId=D1

Zipkin can visualize:

Trace 12345
Gateway -> 10ms
Order Service -> 120ms
Payment Service -> 200ms
Inventory Service -> 40ms

  • TraceId identifies the complete end-to-end request.
  • SpanId identifies a single operation within that request.
Service TraceId SpanId
Gateway 12345 A1
Order Service 12345 B1
Payment Service 12345 C1
Inventory Service 12345 D1
flowchart TD
    T[TraceId: 12345]
    T --> A[Gateway Span A1]
    A --> B[Order Span B1]
    B --> C[Payment Span C1]
    C --> D[Inventory Span D1]
[OrderService, TraceId=12345, SpanId=B1]
Processing Order
[PaymentService, TraceId=12345, SpanId=C1]
Processing Payment
TraceId SpanId
Identifies complete request flow Identifies one operation
Same across all services Different for every service
Used for end-to-end tracking Used for operation-level analysis
One trace contains many spans Each span belongs to one trace

TraceId represents the complete end-to-end request across microservices, while SpanId represents an individual operation within that request.


  • Spring Boot Actuator and Micrometer expose production-ready metrics.
  • Prometheus scrapes metrics, while Grafana visualizes them.
  • Distributed tracing tracks requests across microservices using TraceId and SpanId.
  • Spring Cloud Sleuth automatically propagates tracing context between services.
  • TraceId remains constant for an entire request; SpanId changes for each operation.