Skip to content

Latest commit

 

History

32 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spring Boot Starter Observability

Build Status License Java Spring Boot

A reusable Spring Boot starter that bundles structured logging, distributed tracing (OpenTelemetry), and metrics (Micrometer) into a single dependency. Drop it into any Spring Boot 3.x app and get production-grade observability out of the box — no boilerplate required.

Why?

Every microservice needs observability, but wiring up structured logging, distributed tracing, and metrics from scratch is tedious and error-prone. Teams end up with inconsistent setups across services — different log formats, missing trace context, no correlation between logs and traces.

This starter solves that by providing a single, opinionated dependency that gives you:

  • Structured JSON logging with traceId, spanId, requestId, and correlationId injected into every log line automatically
  • Distributed tracing via OpenTelemetry with automatic span creation for HTTP requests and Kafka messages
  • Metrics via Micrometer with JVM metrics out of the box and custom @Timed / @Counted annotation support
  • Correlation ID propagation across service boundaries via X-Correlation-Id header
  • Graceful degradation — the app starts cleanly even if Jaeger or the OTLP endpoint is unreachable
  • Kafka trace context propagation using W3C traceparent headers

Architecture

graph TD
    subgraph "Your Spring Boot App"
        HTTP["HTTP Request"]
        KAFKA["Kafka Message"]

        subgraph "spring-boot-starter-observability"
            RCF["RequestContextFilter\n(MDC: traceId, spanId,\ncorrelationId, requestId)"]
            TI["TracingInterceptor\n(OTel SERVER span)"]
            KP["Kafka Producer\nInterceptor"]
            KC["Kafka Consumer\nInterceptor"]
            TA["@Traced\n(method spans)"]
            MA["@Timed / @Counted\n(Micrometer)"]
            HI["Health Indicator\n(/actuator/health)"]
        end

        LOG["JSON Logs\n(Logback + MDC)"]
        MET["Micrometer\nMeterRegistry"]
    end

    HTTP --> RCF --> TI --> TA
    KAFKA --> KP
    KAFKA --> KC
    TA --> MA

    TI -- "OTLP gRPC" --> JAEGER["Jaeger"]
    MET -- "scrape" --> PROM["Prometheus"]
    PROM --> GRAFANA["Grafana"]
    LOG --> STDOUT["stdout / log aggregator"]
Loading

Modules

Module Description
starter-core Shared constants and annotations (@Traced, @Timed, @Counted)
starter-autoconfigure All Spring Boot auto-configuration (logging, tracing, metrics, health)
starter-sample Sample CRUD API with full docker-compose stack (Jaeger + Prometheus + Grafana)

Quick Start

Note: This library is under active development and not yet published to Maven Central. Build locally for now.

1. Build locally

git clone https://github.com/ayushwing/spring-boot-starter-observability.git
cd spring-boot-starter-observability
mvn clean install -DskipTests

2. Add the dependency

<dependency>
    <groupId>com.ayushwing</groupId>
    <artifactId>observability-starter-autoconfigure</artifactId>
    <version>0.1.0-SNAPSHOT</version>
</dependency>
<!-- Required transitive runtime deps -->
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.4</version>
</dependency>

3. Configure (all optional — sane defaults provided)

observability:
  logging:
    format: json                        # "json" (default) or "text"
    include-headers: false              # add request headers to MDC
    header-filter: "X-Trace-Id,Accept" # whitelist of headers to include
    include-request-info: true          # add httpMethod + requestUri to MDC
    service-name: ${spring.application.name}
    custom-fields:
      environment: production
      region: us-east-1

  tracing:
    enabled: true
    endpoint: http://localhost:4317     # OTLP gRPC endpoint
    service-name: ${spring.application.name}
    sampling-ratio: 1.0                 # 0.0–1.0
    exporter-timeout-ms: 30000

  metrics:
    enabled: true

Features

Structured JSON Logging

Every log line emitted during an HTTP request automatically includes:

{
  "timestamp": "2024-03-15T10:22:45.123Z",
  "level": "INFO",
  "logger": "com.example.OrderService",
  "message": "Order placed successfully",
  "traceId": "a3f1c2d4...",
  "spanId": "b7e8f9a0",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "correlationId": "7f3a1b2c-...",
  "httpMethod": "POST",
  "requestUri": "/api/orders",
  "service": "order-service"
}

Distributed Tracing

HTTP spans are created automatically for every request. Use @Traced for custom method-level spans:

@Traced("payment.charge")
public Receipt chargeCustomer(String customerId, BigDecimal amount) {
    // This method runs inside its own OpenTelemetry span
    // named "payment.charge" in Jaeger
}

// Exception details are automatically recorded on the span
@Traced(recordException = true)
public Inventory checkStock(String productId) { ... }

Kafka trace context propagates automatically via W3C traceparent headers — no code changes needed.

Metrics with Custom Annotations

JVM metrics (memory, GC, threads, CPU) are registered automatically. Add per-method instrumentation with annotations:

@Timed("orders.process.duration")
public Order processOrder(String orderId) {
    // Records execution time with tags: class, method, exception
}

@Counted("payments.initiated")
public void initiatePayment(Payment payment) {
    // Increments counter with tags: class, method, result (success/failure)
}

Correlation ID Propagation

The X-Correlation-Id header is read on inbound requests (or generated if absent) and:

  1. Stored in MDC as correlationId — appears in every log line
  2. Returned in the response header
  3. Should be forwarded in downstream HTTP calls for full cross-service traceability

Health Check

When spring-boot-actuator is present, a dedicated health indicator is available:

GET /actuator/health/observability

{
  "status": "UP",
  "details": {
    "metrics": "UP",
    "tracing": "UP",
    "logging": "UP"
  }
}

Running the Sample App

The starter-sample module contains a full product CRUD API wired up to the complete observability stack.

cd starter-sample
mvn package -DskipTests -pl .. -am
docker compose up -d
Service URL
Sample API http://localhost:8080/api/products
Actuator Health http://localhost:8080/actuator/health
Jaeger UI http://localhost:16686
Prometheus http://localhost:9090
Grafana http://localhost:3000 (admin / admin)

Try a few requests and watch traces appear in Jaeger:

# List products
curl http://localhost:8080/api/products

# Create a product
curl -X POST http://localhost:8080/api/products \
  -H "Content-Type: application/json" \
  -d '{"name":"Mechanical Keyboard","category":"electronics","price":149.99}'

# Check the correlation ID in the response header
curl -v http://localhost:8080/api/products 2>&1 | grep X-Correlation-Id

Configuration Reference

observability.logging.*

Property Default Description
format json Log format: json or text
include-headers false Include request headers in MDC
header-filter "" Comma-separated header whitelist (empty = all)
include-mdc true Include trace context in log output
include-request-info true Add httpMethod and requestUri to MDC
service-name (spring.application.name) Service name in log output
custom-fields {} Static MDC key-value pairs added to every log line

observability.tracing.*

Property Default Description
enabled true Enable distributed tracing
endpoint http://localhost:4317 OTLP gRPC exporter endpoint
service-name (spring.application.name) Service name in spans
sampling-ratio 1.0 Sampling ratio (0.0–1.0)
exporter-timeout-ms 30000 Flush timeout on shutdown (ms)

observability.metrics.*

Property Default Description
enabled true Enable Micrometer metrics auto-configuration

Tech Stack

  • Java 17+
  • Spring Boot 3.2
  • OpenTelemetry SDK 1.36
  • Micrometer 1.12
  • SLF4J + Logback + logstash-logback-encoder
  • JUnit 5 + Testcontainers + Mockito

Contributing

See CONTRIBUTING.md. Issues and PRs welcome.

License

Apache License 2.0

About

A reusable Spring Boot starter that bundles structured logging, distributed tracing (OpenTelemetry), and health metrics into a single dependency.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages