Spring Boot 4 Observability

OpenTelemetry ve Grafana ile uygulama performansını okumak

Bir Spring Boot 4 uygulamasında OpenTelemetry sinyallerini üretip Grafana üzerinde metrics, traces ve logs ile performans sorunlarını nasıl yorumlayacağını adım adım anlatan pratik rehber. Yazının teknik dayanakları ve resmi doküman bağlantıları en alttaki kaynakça bölümünde yer alıyor.

P95 LATENCY
342 ms
ERROR RATE
1.8%
TRACE WATERFALL
LOG CORRELATION
trace_id

Aynı request'in log, span ve metric bağlantısı.

1. Observability nedir ve monitoring'den farkı nedir?

Monitoring genelde "sistem ayakta mı, CPU kaç, memory kaç, hata var mı?" sorularına cevap verir. Observability ise daha ileri gider: sistemin iç durumunu dışarıdan üretilen sinyallerle anlamaya çalışır. Yani sadece alarm görmek değil, alarmın nedenini bulmak için iz bırakmaktır.

Spring Boot 4 tarafında bu yaklaşım Micrometer Observation, OpenTelemetry ve OTLP exporter akışıyla kurulabilir. Grafana tarafında ise bu sinyaller dashboard, trace waterfall, log araması ve alert panelleriyle okunur.

Metrics

Sayısal ölçümlerdir. Request süresi, hata oranı, JVM memory, thread sayısı gibi değerleri zaman içinde gösterir.

Traces

Bir isteğin servisler ve katmanlar arasında hangi adımlardan geçtiğini, her adımın kaç ms sürdüğünü gösterir.

Logs

Uygulamanın olay günlüğüdür. Hata detayı, iş akışı, parametre ve karar noktaları için bağlam sağlar.

2. Metrics, traces ve logs nasıl yorumlanır?

İyi bir teşhis akışı genelde metrics ile başlar, traces ile daralır, logs ile kanıtlanır. Örneğin Grafana'da P95 latency 300 ms'den 900 ms'ye çıktıysa önce hangi endpoint'in yavaşladığını görürsün. Sonra trace waterfall'da yavaş span'i bulursun. En son aynı `trace_id` ile loglara gidip sebebi okursun.

Latency değerlerini okuma

HTTP Controller
38 ms
Service Layer
64 ms
PostgreSQL
420 ms
External API
710 ms
Yorumlama mantığı

Ortalama latency tek başına yeterli değildir. P50 normal kalırken P95/P99 yükseliyorsa kullanıcıların küçük ama önemli bir kısmı ciddi yavaşlık yaşıyor olabilir. Grafikte ani spike varsa deploy, cache miss, database lock, thread pool saturation veya external API gecikmesi düşünülmelidir.

Metric okurken

  • P95/P99 latency trendine bak.
  • Error rate ile latency aynı anda yükseliyor mu kontrol et.
  • CPU düşük ama latency yüksekse I/O veya lock beklemesi olabilir.
  • Thread sayısı ve queue depth artıyorsa concurrency baskısı vardır.

Trace okurken

  • En uzun span'i bul.
  • DB, cache, HTTP client span'lerini ayrı ayrı incele.
  • Parent-child ilişkisini takip et.
  • Aynı trace içindeki error tag ve log correlation alanlarına bak.

3. Spring Boot 4 bazlı kurulum: dependency, OTLP endpoint ve Grafana stack

Spring Boot 4 ile temel yaklaşım şudur: uygulama telemetry sinyallerini OTLP formatında dışarı verir, OpenTelemetry Collector bu sinyalleri alır, Grafana ekosistemi ise metrics, traces ve logs tarafını görselleştirir. Basit lokal kurulumda Grafana, Tempo ve Loki yeterlidir; production'da collector mutlaka araya konulmalıdır.

Maven dependencySpring Boot 4.0.5
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.0.5</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-opentelemetry</artifactId>
    </dependency>
</dependencies>
application.ymlOTLP export
spring:
  application:
    name: finance-portal-api

management:
  opentelemetry:
    resource-attributes:
      service.name: finance-portal-api
      service.namespace: portfolio
      deployment.environment: local
  otlp:
    tracing:
      endpoint: http://localhost:4318/v1/traces
    metrics:
      export:
        url: http://localhost:4318/v1/metrics
    logging:
      endpoint: http://localhost:4318/v1/logs
  observations:
    key-values:
      region: eu-central-1
      stack: local
OpenTelemetry Collectorotel-collector.yml
receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318
      grpc:
        endpoint: 0.0.0.0:4317

processors:
  batch:

exporters:
  otlp/tempo:
    endpoint: tempo:4317
    tls:
      insecure: true
  loki:
    endpoint: http://loki:3100/loki/api/v1/push
  prometheus:
    endpoint: 0.0.0.0:9464

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp/tempo]
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [loki]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [prometheus]
Not

Spring Boot dokümantasyonu OpenTelemetry için farklı yollar olduğunu söyler: Java agent, OpenTelemetry Spring Boot starter veya Spring'in Micrometer/OTLP yaklaşımı. Spring Boot 4 örneğinde hedefimiz vendor-neutral telemetry üretmek ve Grafana tarafında yorumlamaktır.

4. Grafana'da süreç okuma: dashboard'dan trace'e, trace'den log'a

Grafana'da iyi bir inceleme akışı panikten uzak olmalıdır. Önce büyük resmi görürsün: request rate, error rate, latency histogramları, JVM memory, GC pause, active threads. Sonra problemli endpoint veya servis seçilir. Ardından trace detayına gidilir ve log korelasyonu yapılır.

1. Dashboard

Latency ve error rate spike'ını yakala. Hangi servis ve endpoint etkilenmiş bunu bul.

2. Trace

Request içindeki en uzun span'i bul. DB mi, external API mi, lock beklemesi mi ayır.

3. Log

Aynı trace id ile loglara git. Exception, retry, timeout veya business rule kararını oku.

Örnek yorum

Diyelim `/api/portfolio/summary` endpoint'i normalde P95 olarak 180 ms çalışıyor. Deploy sonrası P95 740 ms oldu. Trace waterfall'da controller 20 ms, service 45 ms ama PostgreSQL span'i 620 ms görünüyor. Bu durumda controller koduna değil, query plan, index, lock, connection pool ve N+1 sorgu ihtimaline odaklanırsın.

5. Multithreading ortamda izleme: context propagation neden kritik?

Observability verisi çoğu zaman `ThreadLocal` bağlamla taşınır: trace id, span id, baggage gibi bilgiler mevcut execution context içinde tutulur. Eğer iş başka thread'e atılırsa bu bağlam kaybolabilir. Sonuçta trace kopuk görünür, loglar trace id taşımayabilir ve Grafana'da request bütünlüğü bozulur.

Context propagationSpring Boot 4
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.support.ContextPropagatingTaskDecorator;

@Configuration(proxyBeanMethods = false)
class ObservabilityContextConfiguration {

    @Bean
    ContextPropagatingTaskDecorator contextPropagatingTaskDecorator() {
        return new ContextPropagatingTaskDecorator();
    }
}
Neden önemli?

`@Async`, `AsyncTaskExecutor`, custom executor, scheduler veya virtual thread executor kullanırken request context başka çalışma hattına geçer. Context propagation yoksa aynı request'in parçaları Grafana'da ayrı olaylarmış gibi görünür.

İzlenecek metrikler

  • Active threads ve queued tasks
  • Executor queue wait time
  • Task duration histogram
  • Rejected task count
  • Lock wait veya DB connection wait

Trace tarafında bakılacaklar

  • Async span parent-child ilişkisi korunmuş mu?
  • Thread geçişinden sonra trace id aynı mı?
  • Long-running task ayrı span olarak görünüyor mu?
  • Timeout/retry span event olarak işlenmiş mi?

6. Best practices: production'da okunabilir telemetry üretmek

Service name standardı koy `service.name`, `service.namespace`, `deployment.environment`, `region` gibi alanlar her serviste tutarlı olmalı. Yoksa dashboard filtreleri anlamsızlaşır.
High cardinality tag'leri metrics'e koyma `userId`, `orderId`, `traceId` gibi değerler metrics label olursa zaman serisi patlar. Bunları trace/log tarafında kullan.
Latency histogramlarını endpoint bazlı oku Sadece global latency bakma. `/login`, `/portfolio/summary`, `/orders` ayrı davranır.
Logs, traces ve metrics'i korele et Log formatında trace id ve span id varsa Grafana'da tek request'in tüm hikayesi okunur.
Alert'i semptoma, trace'i nedene bağla Alert "P95 800 ms oldu" der. Trace "PostgreSQL span'i 650 ms sürdü" diye nedeni daraltır.
En yaygın hata

Her şeyi loglamak observability değildir. Çok log üretmek maliyeti artırır ve problemi bulmayı zorlaştırır. İyi telemetry az ama anlamlı alanlarla, tutarlı isimlerle ve korelasyon id'leriyle üretilir.

Kaynakça

Bu yazıdaki Spring Boot 4 observability yaklaşımı, OpenTelemetry entegrasyon seçenekleri ve Grafana'da metrics/logs/traces yorumlama akışı aşağıdaki resmi dokümanlar temel alınarak hazırlandı.