# Mikroservislerde dağıtık izlemeyi (OpenTelemetry) nasıl kurarım?

> W3C Trace Context'te standartlaşıp propagation'ı OTel SDK'ya bırakın ve traceparent'ı kuyruk mesajının header'ına koyun; zincir orada kopuyor.

- Soruldu: 2026-05-06
- Yanıtlandı: 2026-05-09
- Soran: Ece
- Etiketler: mimari, observability, mikroservis
- Kaynak: https://www.muhammetsafak.com.tr/sor-bakalim/mikroserviste-dagitik-izleme-opentelemetry-ile-nasil-kurulur/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
**Soru:** Bir istek API Gateway → Auth → Sipariş → Stok sırasıyla geziyor. Aradaki bir serviste 800ms gecikmenin kaynağını bulmakta zorlanıyoruz. OpenTelemetry ile tüm servisler (Laravel ve Go) arasında `trace_id` taşıyıp merkezi APM'de (Jaeger/Grafana Tempo) görselleştirmeyi planlıyoruz.

HTTP header'ları ve kuyruk mesajları üzerinden context propagation'ı nasıl tasarlarım?


Kısa cevap: Custom bir şema icat etmeyin; **W3C Trace Context** (`traceparent`/`tracestate`) üzerinde standartlaşın ki PHP ve Go birbirini sorunsuz anlasın.

Sizin asıl derdiniz "800ms nerede" — ve bunu görebilmek için trace'in servisler ve kuyruklar arasında **kopmadan** taşınması gerekiyor. Mekanizma şu:

1. **W3C Trace Context'i standart yapın.** Gateway'de kök span'i başlatın; her servis gelen HTTP header'ından context'i **extract** etsin, giden çağrılara **inject** etsin. Standart başlık olduğu için Laravel ve Go aynı `traceparent`'ı ortak okur — kendi `trace_id` başlığınızı uydurmayın.
2. **Kuyruklarda aynı `traceparent`'ı mesajla taşıyın.** Mesajı publish ederken `traceparent`'ı bir mesaj header'ı/attribute olarak ekleyin, worker'da yeniden **extract** edin. Takımların unuttuğu tam olarak bu parçadır; yapmazsanız asenkron sıçramalar APM'de **orphan trace** olarak görünür ve zincir kopar.
3. **Her servise OTel SDK koyun, OTLP ile gönderin.** Servis → OTLP → bir **Collector** → Jaeger/Tempo. Collector'ı araya almak, export'u uygulamadan ayırır ve backend değiştirmeyi kolaylaştırır.
4. **Sampling'i akıllı seçin.** `parent-based` ile bir trace'in tüm span'leri aynı kaderi paylaşsın; üstüne **tail sampling** ekleyin ki 800ms'lik outlier'ları kesin tutun. Head-only sampling'de tam da görmek istediğiniz yavaş trace'i atarsınız.
5. **trace_id'yi elle örmeyin.** Kendi elinizle header okuma/yazma kodu yazmayın; SDK'nın context propagation'ı bunu zaten taşır. Elle yapınca bir yerde unutursunuz ve trace o noktada kopar.

**Sonuç:** Ben olsam W3C Trace Context + OTel SDK + Collector + Tempo/Jaeger kurar, propagation'ı SDK'ya bırakır, kuyruk hop'unda `traceparent`'ı mesaj header'ına koymayı asla atlamazdım. Mimari muhakemeyi neden böyle kurduğunuzu sade.dev'de anlatıyorum; Go tarafındaki HTTP mekaniğinin detayını da hub yazısında bulursunuz. 800ms'i ancak kopmamış bir trace gösterir.

## İlgili Yazılar

- [Go'da HTTP servisi yazmak: standart kütüphane yeter mi](/blog/go-da-http-servisi-yazmak-standart-kutuphane-yeter-mi/) — Blog
- [Mikroservise Ne Zaman Geçerim?](https://sade.dev/tr/journal/mikroservise-ne-zaman-gecerim) — sade.dev
- [Yeni bir projeye mikroservislerle mi başlamalıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/yeni-projeye-mikroservisle-mi-baslamali/) — Sor Bakalım
- [PHP monolitten ödeme modülünü Strangler Fig ile nasıl koparırım?](https://www.muhammetsafak.com.tr/sor-bakalim/monolitten-mikroservise-strangler-fig-ile-kademeli-gecis/) — Sor Bakalım
- [Laravel ve Go servisleri arasında mesaj şeması için Protobuf mu, JSON Schema mı?](https://www.muhammetsafak.com.tr/sor-bakalim/laravel-ve-go-arasinda-mesaj-semasi-protobuf-mu-json-schema-mi/) — Sor Bakalım
