Distributed tracing nasıl çalışır? Trace context servisler arasında nasıl taşınır ve OpenTelemetry'nin rolü nedir?

Cevap

Bir trace, tek bir isteğin sistemdeki tüm yolculuğudur; her adım bir span'dir (başlangıç/bitiş zamanı, servis, işlem adı, attribute'lar, hata durumu). Span'lar trace_id ile aynı trace'e, parent_span_id ile birbirine bağlanarak bir ağaç oluşturur.

trace_id=4bf9...
└─ GET /checkout            api-gateway      320ms
   ├─ POST /orders          order-service    250ms
   │  ├─ INSERT orders      postgres          12ms
   │  └─ POST /charge       payment-service  210ms   <- darboğaz
   └─ GET /cart             cart-service      40ms

Context propagation

Servisler arası çağrılarda trace bilgisi W3C Trace Context standardındaki traceparent başlığıyla taşınır:

traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
             ver-trace_id (16 byte)-----------------parent_span_id--flags(sampled)
  • HTTP/gRPC çağrılarında header'da, Kafka/RabbitMQ mesajlarında mesaj header'ında taşınır.
  • Süreç içinde ise context dilin mekanizmasıyla taşınır: Java'da ThreadLocal/Context, Node.js'te AsyncLocalStorage, .NET'te Activity.Current, Python'da contextvars.
  • Zincirdeki bir servis header'ı iletmezse trace orada kopar; en yaygın sorun budur.

OpenTelemetry (OTel)

Vendor bağımsız açık standart ve SDK setidir (CNCF):

  • API/SDK: span, metric ve log üretimi.
  • Auto-instrumentation: HTTP sunucu/istemci, DB sürücüleri, kuyruk kütüphaneleri için kod değiştirmeden span üretir (Java agent, .NET, Node.js, Python).
  • OTLP protokolü ve Collector: veriyi toplar, işler (filtreleme, sampling) ve Jaeger, Tempo, Datadog gibi istediğiniz backend'e gönderir. Backend değiştirmek uygulama kodunu etkilemez.
const tracer = trace.getTracer("order-service");
await tracer.startActiveSpan("reserve-stock", async (span) => {
  span.setAttribute("order.id", orderId);
  try { await reserve(orderId); }
  catch (e) { span.recordException(e); span.setStatus({ code: SpanStatusCode.ERROR }); throw e; }
  finally { span.end(); }
});

Sampling

Tüm istekleri saklamak pahalıdır.

  • Head-based: karar trace başında verilir (ör. %10). Basit ama nadir hataları kaçırabilir.
  • Tail-based: trace tamamlanınca Collector karar verir; hatalı veya yavaş trace'lerin hepsi saklanır, normal olanların küçük bir kısmı.
  1. Observability nedir? Log, metric ve trace arasındaki fark nedir ve her biri ne için kullanılır?KolayDocker & DevOpsBackend
  2. Rolling update, blue-green ve canary deployment stratejileri arasındaki farklar nelerdir?OrtaDocker & DevOpsBackend
  3. Ortam değişkenleri ve secret'lar (şifre, API anahtarı) güvenli şekilde nasıl yönetilir?OrtaDocker & DevOpsBackend
  4. CI/CD nedir? Tipik bir backend CI/CD pipeline'ının aşamaları nelerdir?OrtaDocker & DevOpsBackend
  5. İyi bir Dockerfile nasıl yazılır? Multi-stage build ne işe yarar?OrtaDocker & DevOpsBackend
  6. Docker Compose ne işe yarar? Basit bir örnekle açıklayın.KolayDocker & DevOpsBackend

Bu konuda başka bir soru biliyor musun?

Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.

Soru ekle