Blog
Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.
Observability Nedir? Monitoring'den Farkı, Log, Metric ve Trace'in Her Birinin Cevapladığı Soru
Observability, sistemin dışarıya verdiği log, metric ve trace sinyallerinden önceden düşünülmemiş bir soruyu sonradan sorup cevaplayabilmektir; monitoring ise bilinen arızaları izler. Bookstore'da bazen 8 saniye süren checkout'u log, dotnet-counters ile metric ve trace üzerinden daraltıyor, telemetry pipeline'ını ve cardinality maliyetini tanıyoruz.
OpenTelemetry'nin Yapısı ve .NET'te İlk Kurulum: SDK, Instrumentation, OTLP, Resource ve Aspire Dashboard
OpenTelemetry'yi .NET'e eklemek için AddOpenTelemetry ile resource, instrumentation ve UseOtlpExporter kurulur; ILogger, Meter ve ActivitySource zaten platformda olduğu için SDK yalnızca onları toplayıp OTLP ile gönderir. Bookstore.Api'yi 1.21 paketleriyle kuruyor, yavaş checkout'un trace'ini standalone Aspire Dashboard'da açıyor, koddaki AddService'in OTEL_SERVICE_NAME'i ezdiği tuzağı ve sessiz export hatalarını görüyoruz.
.NET'te Metric Üretmek: Counter, Histogram, Gauge, Built-in Metric'ler ve Cardinality Bütçesi
.NET'te metric, IMeterFactory'den alınan bir Meter'ın instrument'larıyla üretilir: sayaç için Counter, artıp azalan toplam için UpDownCounter, süre için Histogram, dışarıdan set edilen anlık değer için Gauge. Bookstore'un checkout metric'lerini yazıyor, built-in metric'leri ve RED/USE yöntemlerini tanıyor, MetricCollector ile test ediyor ve SDK'nın 2000'lik cardinality sınırında ne yaptığını ölçüyoruz.
Distributed Tracing: Span, Context Propagation, W3C traceparent ve ActivitySource ile Özel Span'ler
Distributed tracing, bir isteğin geçtiği her adımı aynı trace id'yi taşıyan span'lar olarak kaydeder; .NET'te span bir Activity'dir ve servisler arasında W3C traceparent header'ıyla taşınır. Bookstore'un checkout'una ActivitySource ile span'lar ekliyor, exception ve status kaydediyor, retry'ların traceparent'ını, baggage'ı, bir queue üzerinden propagation'ı, null Activity'yi ve tarayıcıdan trace başlatmanın bugünkü durumunu görüyoruz.
OpenTelemetry Collector: Receiver, Processor, Exporter, Tail Sampling ve PII Filtreleme
OpenTelemetry Collector, uygulamayı backend'den ayıran ve telemetry'yi receiver, processor ve exporter'lardan oluşan pipeline'larla alıp işleyen ayrı bir process'tir. Bookstore için tek container'lık bir LGTM stack'inde Collector'ı kuruyor, gereksiz log'ları filtreliyor, e-posta adresini hash'liyor, tail sampling ile hatalı ve yavaş trace'leri tutuyor ve head sampling'in şikâyet edilen siparişlerin yüzde 90'ını nasıl attığını ölçüyoruz.
Prometheus ve PromQL: Scrape mi Push mu, rate, histogram_quantile, Recording Rule'lar ve Native Histogram'lar
.NET metric'leri Prometheus'a iki yoldan girer: beta durumundaki exporter'ın /metrics endpoint'ini scrape etmek ya da OTLP ile Prometheus 3'ün OTLP receiver'ına push etmek. Bookstore'un metric'leriyle rate, increase, histogram_quantile ve hata oranı sorgularını, isim çevirisini, recording rule'ları ve klasik bucket'larla native histogram'ların yüzdelik doğruluğunu ölçerek karşılaştırıyoruz.
Grafana ile Dashboard: RED ve USE Dashboard'ları, Variable'lar, Exemplar ile Metric'ten Trace'e ve Dashboard as Code
İyi bir Grafana dashboard'u tek bir soruya cevap verir: RED servisin sağlığını, USE kaynakların doygunluğunu gösterir. Bookstore için iki dashboard'u JSON olarak Git'te tutup provisioning ile yüklüyor, variable'ları target_info'dan besliyor ve exemplar ile p99 sıçramasından yavaş isteğin trace'ine geçiyoruz; tail sampling'in exemplar'ları neden boşa düşürdüğünü de ölçüyoruz.
Trace Backend'i ile Yavaş İsteği Bulmak: Jaeger v2, Grafana Tempo ve Checkout'taki N+1 Sorgusu
Yavaş isteği trace backend'inde bulmak, doğru soruyu sormaya bağlı: Jaeger v2 index'li tag aramasıyla, Tempo ise TraceQL ile span'lar arası koşullarla arıyor. Bookstore'un 7,6 saniyelik checkout'unu waterfall'da açıp retry fırtınasını ve N+1 sorgusunu buluyor, iki düzeltmeyi ve hedging'i ölçüyor, tail sampling'li trace'lerden yüzdelik hesaplamanın neden yanılttığını gösteriyoruz.
Log Backend'leri: OpenTelemetry Logs, Loki ve ELK — Label, LogQL ve Log'dan Trace'e Geçiş
Loki'de log'u ucuz tutmanın yolu label'ları az tutmak: OpenTelemetry log'unun resource attribute'larının bir kısmı label, geri kalanı ve trace_id structured metadata oluyor. Bookstore'da template'li log gövdesini, her restart'ta yeni stream açan service.instance.id'yi ve LogQL ile hata, seviye, süre ve log'dan trace'e geçiş sorgularını gerçek çıktılarla inceliyor; ELK, OpenSearch ve Seq'i karşılaştırıyoruz.
Alerting: Semptom Tabanlı Alarm, Alertmanager, Grafana Alerting, Runbook ve Alarm Yorgunluğu
Alarm, kullanıcının hissettiği semptoma kurulur ve her birinin bir runbook'u olur; sebepler page değil ticket'tır. Bookstore için burn-rate, süre, retry, telemetry yokluğu ve Watchdog alarmlarını Prometheus'ta yazıp Alertmanager ile yönlendiriyor, gruplama, silence ve inhibition'ı gerçek bir arıza üzerinde görüyor, API düştüğünde hata oranı alarmının neden sustuğunu ölçüyoruz.
Production'da Observability: Azure Monitor ve Application Insights, Sampling, Maliyet, PII ve Kubernetes'te Otomatik Instrumentation
Production'da telemetry'nin maliyeti ve riski sampling, hacim ve kişisel veriyle yönetilir: tail sampling varken uygulamada head sampling yapmak yavaş trace'lerin çoğunu kaybettirir. Bookstore'da iki ayarı ölçüyor, sipariş başına span, log ve seri bütçesi çıkarıyor, PII'yi Loki'de denetliyor; Azure Monitor için yeni Microsoft OpenTelemetry Distro'yu, semantic convention geçişlerini ve Kubernetes Operator'ünü inceliyoruz.
.NET 8'den .NET 11'e Observability'de Gelenler: IMeterFactory, Gauge, Yeni Built-in Metric'ler ve ASP.NET Core'da Yerleşik Tracing
.NET 11'de ASP.NET Core, HTTP server span'ının OpenTelemetry attribute'larını kendisi yazıyor ve MemoryCache dotnet.cache.* metric'lerini yayınlıyor; instrumentation paketi gerekmiyor. .NET 8'in IMeterFactory'sinden .NET 9'un Gauge'una, .NET 10'un Identity metric'leri ve schema URL'ine kadar sürüm haritasını çıkarıyor, .NET 11 maddelerini GA SDK'sıyla çalıştırıp eski kodu okumanın ipuçlarını veriyoruz.