37 puan yazan GN⁺ 2025-12-22 | 1 yorum | WhatsApp'ta paylaş
  • Modern dağıtık sistemlerde geleneksel loglama yaklaşımı, gerçeği aktaramayan yapısal sınırlara sahiptir
  • Loglar hâlâ 2005 tarzı tek sunucu ortamı varsayımıyla tasarlanır; bu yüzden birden çok servis, veritabanı ve cache üzerinden geçen isteğin bağlamını kaybeder
  • Basit metin araması yapıyı, ilişkileri ve korelasyonu anlayamaz; bu da sorunun kök nedenini bulmayı zorlaştırır
  • Çözüm, her istek için tüm bağlamı içeren tek bir Wide Event (veya Canonical Log Line) bırakmaktır
  • Böylece loglar basit metin olmaktan çıkıp analiz edilebilir bir veri varlığına dönüşür

Loglamanın temel sorunu

  • Mevcut loglar monolitik sunucu çağı varsayımıyla oluşturulduğundan, modern dağıtık servis mimarisini yansıtamaz
    • Bir istek birden fazla servis, DB, cache ve kuyruktan geçse de loglar hâlâ tek sunucu ölçütüne göre tutulur
  • Örnek loglarda istek başına 13 satır üretiliyor; bu da aynı anda 10.000 kullanıcı varken saniyede 130.000 satır demek, ama bunların çoğu anlamsız bilgi
  • Sorun çıktığında gereken şey **bağlam (context)**tır, ancak mevcut loglarda bu eksiktir

Metin aramasının sınırları

  • Kullanıcı “ödeme çalışmıyor” diye bildirdiğinde, loglarda e-posta veya user_id ile arama yapsanız bile tutarlı bir yapı olmadığı için anlamlı sonuç almak zordur
    • Aynı kullanıcı kimliği user-123, user_id=user-123, {"userId":"user-123"} gibi onlarca farklı biçimde kaydedilir
  • Servisler arasında log formatı değiştiğinden ilişkili olayları takip etmek imkânsızdır
  • Temel sorun, logların yazma (write) odaklı tasarlanmış olması ve sorgu (query) için optimize edilmemesidir

Temel kavramların tanımı

  • Structured Logging: metin yerine anahtar-değer (JSON) biçiminde kayıt tutma yaklaşımı
  • Cardinality: bir alanın benzersiz değer sayısı; örneğin user_id çok yüksektir
  • Dimensionality: bir log olayındaki alan sayısı; sayı arttıkça analiz imkânı da artar
  • Wide Event / Canonical Log Line: istek başına bağlamı zengin tek bir log olayı
  • Çoğu loglama sistemi yüksek cardinality'li veriyi maliyet nedeniyle sınırlar, oysa hata ayıklamada en faydalı olan tam da budur

OpenTelemetry'nin sınırları

  • OpenTelemetry (OTel), yalnızca protokol ve SDK setidir; veri toplama ve iletme için standart sağlar
  • Ancak OTel şunları yapmaz
    1. Neyin loglanacağına karar vermez
    2. İş bağlamını (ör. abonelik seviyesi, sepet tutarı vb.) otomatik olarak eklemez
    3. Geliştiricinin loglama düşünce biçimini değiştirmez
  • Aynı kütüphane kullanılsa bile, bağlamı bilinçli biçimde ekleyen enstrümantasyon ile basit enstrümantasyon arasında hata ayıklama deneyimi dramatik biçimde farklıdır
  • OTel sadece bir taşıma hattıdır (plumbing); içinden neyin akacağını geliştirici belirlemelidir

Wide Event / Canonical Log Line yaklaşımı

  • Geleneksel “kod ne yapıyor?” merkezli loglamadan çıkıp, “isteğe ne oldu?”yu kaydetmek gerekir
  • Her istek için servis düzeyinde tek ve kapsamlı bir olay üretilir
    • İstek, kullanıcı, ödeme, hata, ortam gibi 50'den fazla alan içerebilir
  • Örnek JSON'da user_id, subscription_tier, service_version, error_code gibi hata ayıklama için gereken tüm bağlam yer alır
  • Bu sayede “premium kullanıcıların ödeme başarısızlığının nedeni” gibi sorular tek aramayla anında analiz edilebilir

Wide Event için sorgu kullanımı

  • Wide Event, basit metin aramasıyla değil yapılandırılmış veri sorguları ile ele alınır
  • Yüksek cardinality ve yüksek boyutlu veri sayesinde gerçek zamanlı analiz seviyesinde hata ayıklama mümkün olur
  • Örneğin “son 1 saatte premium kullanıcıların ödeme başarısızlık oranını hata koduna göre grupla” gibi bir sorgu anında çalıştırılabilir

Uygulama deseni

  • Olay, isteğin tüm yaşam döngüsü boyunca oluşturulur ve yalnızca en sonda bir kez yazdırılır
    • Middleware içinde request_id, timestamp, method, path gibi temel alanlar başlatılır
    • Handler içinde kullanıcı, sepet, ödeme ve hata bilgileri aşamalı olarak eklenir
  • Sonunda logger.info(event) ile tek bir JSON olay kaydedilir

Sampling ile maliyet kontrolü

  • İstek başına 50'den fazla alan kaydedildiğinde maliyet hızla arttığından sampling gerekir
  • Basit rastgele sampling, hataları kaçırma riski taşır
  • Önerilen strateji: Tail Sampling
    1. Hatalar (500 vb.) her zaman saklanır
    2. Yavaş istekler (p99 ve üzeri) her zaman saklanır
    3. VIP kullanıcılar ve belirli flag'lere sahip oturumlar her zaman saklanır
    4. Geri kalanların yalnızca %1~5'i rastgele örneklenir
  • Böylece maliyet azaltımı ile kritik olayların korunması aynı anda sağlanır

Yaygın yanlış anlamalar

  • Structured Logging ≠ Wide Event: Sadece JSON formatı yeterli değildir; asıl önemli olan bağlamdır
  • OpenTelemetry kullanmak ≠ tam gözlemlenebilirlik sağlamak: Sadece toplamayı standartlaştırır; neyin kaydedileceği geliştiriciye kalır
  • Tracing ile aynı şey değildir: Tracing servisler arası akışı gösterir, Wide Event ise servis içi bağlam sağlar
  • Loglar hata ayıklama için, metrikler dashboard için” ayrımı gereksizdir — Wide Event her iki kullanım amacını da karşılar
  • Yüksek cardinality'li veri pahalıdır” düşüncesi artık eskidi; ClickHouse, BigQuery gibi modern veritabanları bunu verimli biçimde işleyebilir

Wide Event benimsemenin etkisi

  • Hata ayıklama, kazı çalışmasından (archaeology) analitiğe (analytics) dönüşür
  • “Kullanıcının ödeme başarısızlığını” bulmak için 50 servisin loglarını grep ile tarama yaklaşımından,
    “premium kullanıcıların ödeme başarısızlık oranını hata koduna göre sorgulama” gibi tek sorgu tabanlı analize geçilir
  • Sonuç olarak loglar, yalan söyleyen bir araçtan gerçeği anlatan bir veri varlığına dönüşür

1 yorum

 
GN⁺ 2025-12-22
Hacker News görüşleri
  • Yazının okunması zordu ve AI yardımıyla yazılmış gibi bir havası vardı. Yine de mesajı değerliydi; biraz daha özlü olsaydı daha iyi olurdu.
    Son zamanlarda düşündüklerim şunlar.

    • Kimlik doğrulama tüm stack boyunca bulunduğu için tüm log satırlarına user id eklemeye başladım. Bu sayede kullanıcının yaşadığı deneyimi uçtan uca görmek kolaylaştı
    • Hataları istek logundan ayrı bir satırda kaydetmek zahmetli. Trace ile filtrelenebiliyor ama “yalnızca 5xx istekleriyle ilişkili hataları göster” gibi sorgular yazmak zor
    • Bu tür bağlamları eklemek tek başına yetmiyor; ekip arkadaşlarına da yeni alanların oluştuğunu öğretmek gerekiyor. Bunu bilmedikleri için kendi kendilerine zorlandıklarını çok gördüm
    • Daha iyi tracing araçlarına yatırım yapmak, basit loglarla mümkün olmayan düzeyde debugging yapmayı sağlıyor. Bu, user id’yi trace olarak kullanma fikrinin genişletilmiş hali gibi
    • Kod tabanında request ID kavramı varsa, onunla da kullanıcının davranışı daha ayrıntılı izlenebilir
    • TID’yi servis genelinde zorunlu hale getirirseniz, hangi ekip olursa olsun tek bir TID ile tüm transaction izlenebilir
    • Bu tür “AI kokuyor” tarzı yorumlar yakında eleştirilen bir kültür haline gelecek gibi görünüyor
  • Bu konuda Charity Majors’tan bahsetmemek olmaz. Kendisi 10 yıldan uzun süredir “wide events” ve “observability” kavramlarını yaygınlaştırıyor ve Honeycomb.io’yu bu felsefe üzerine kurdu.
    Bugün bu yaklaşım farklı araçlarla uygulanabiliyor. Structured logs ya da traces ile wide event’leri yakalayıp zaman serisi, histogram gibi güçlü görselleştirmeleri olan araçlar kullanmak önemli

    • Yine de “observability” terimini bizzat onun ortaya attığı söylenemez. Bu kavram zaten onlarca yıldır çeşitli alanlarda kullanılıyordu. Kendisi etkili bir uygulayıcı ama terimin yaratıcısı değil
    • Blogu ve Honeycomb’un ortaya çıkış hikâyesi sektörde çalışan herkesin okuması gereken şeyler. Bu yaklaşımın değerini ilk fark eden ekiplerden biriydiler
    • Yazı onun tarzına o kadar benziyordu ki sonunda Honeycomb reklamı çıkacak sandım; çıkmamasına şaşırdım
    • .NET ekosisteminde Nick Blumhardt, “structured logging” konusunu çok uzun zaman önce ele aldı; Seq ve Serilog da bunu destekliyordu
    • İçerikleri iyi ama “observability”yi markalaştıran tek kişi diye düşünmemek lazım. Saygı duymak gerek ama abartılı iddialardan kaçınmak da gerek
  • Yazının savlarının bazılarına katılıyorum ama yalnızca tek bir wide event bırakma yaklaşımının tuzakları var. İstek ortasında exception ya da timeout olursa geriye hiçbir şey kalmayabilir.
    Dilin varsayılan logging framework’ünü veya bağımlılık loglarını da kaçırabilirsiniz.
    Bu yüzden bunu mevcut logların üstüne gelen ek bir katman olarak kullanmak daha iyi. Request/session düzeyinde ID ekleyip ClickHouse gibi bir yerde toplulaştırabilirsiniz

    • Sorun ara katmandaki görünürlükse, olay yeterince wide değildir. log.error(data) ile wide_event.attach(error, data) arasında özde büyük fark yok
    • “connection X:Y accepted at Z ns” ve “closed at Z ns” gibi loglar, yavaş sistemleri debug etmekte çok işe yarar
    • Ben bunu PHP framework’ümde bir LoggerInterface oluşturarak çözdüm. Exception’ları global handler ile yakalayıp veritabanına wide biçimde kaydediyorum. Biraz boilerplate var ama o kadar iyi çalışıyor ki artık onsuz olmak rahatsız ederdi
  • Sunum ve interaktif örnekler harikaydı. Ama sonuçta anlatılan şey “loglara yapılandırılmış etiketler ekleyin” noktasına geliyor.
    Wide log’ların getirdiği karmaşıklık ve okunabilirlik kaybına kıyasla sağladığı faydanın çok büyük olmadığını düşünüyorum.
    Sadece grep "uid=user-123" application.log yeterliyken, kullanıcının teslimat yöntemini de eklemeye gerçekten gerek var mı emin değilim.
    (Bu arada Android’de Brave tarayıcısında checkbox’lar çalışmıyordu)

    • JSON loglarda da hâlâ grep '"uid": "user-123"' ile arama yapılabilir. --context seçeneğiyle çevredeki satırlar da görülebilir
  • Yarı iletken üretim ortamında binlerce message bus katılımcısı olan sistemlerle çalıştım. Saatte 300~400MB log çıkıyordu ama grep ve CLI araçlarıyla bile rahatça yönetiliyordu.
    Loglar yalnızca olayların zaman serisi gibiydi; ayrıntılı analiz Oracle sorgularıyla yapılıyordu. Log, olayların nedensel ilişkisini anlamaya yarayan bir araçtır

    • Loglar zaman çizelgesini anlamak içindir; istek/yanıtın tüm verisini taşımak için değil. Fazla bilgi koyarsanız anlamak daha da zorlaşır.
      Log “ne zaman, ne oldu”yu söyler; “neden” ise kod, veri ve olayların birleşiminde bulunur
      Benim için ELK stack gibi arayüzler sezgisel keşif açısından pek rahat değil. Logları içgüdüsel olarak takip ederek okumak önemlidir
    • Saatte 400MB log aslında çok büyük bir miktar değil. O yüzden basit grep çoğu durumda yeterli olur
  • Yazının sonunda geçen “tüm hata, exception ve yavaş istekleri loglayın” tavsiyesi tehlikeli bir fikir.
    Örneğin bir bağımlılık yavaşlarsa log hacmi 100 kat artabilir.
    Arıza anında servisin daha az iş yapması gerekir ki toparlanabilsin; log patlaması ise tam tersine zincirleme arızalara yol açabilir

    • Cloudflare, uyarlanabilir örnekleme kullanıyor. Log partilerini alanlara göre bucket’lara ayırıp her bucket’ta gelen log sayısının karekökü ya da logaritması kadarını tutuyorlar.
      Log miktarı arttıkça örnekleme oranı otomatik ayarlanıyor ve sistem aşırı yüklenmiyor
    • Bu tür sihirli eşikler risklidir. P(99) gibi değerler dinamik güncellenmeli. OTEL provider’dan düzenli olarak gerçek değerleri almak daha güvenlidir
    • Production servisleri, log toplamanın talebe göre ölçekleneceği şekilde tasarlanmalı. Yalnızca yerel disk tamponlaması bile büyük fayda sağlar
    • Yüksek trafikli servislerde trace_id mod 100 == 0 gibi yöntemlerle sağlıklı istekleri örneklemek yeterli olabilir
    • Eğer loglar darboğaz oluyorsa, sistem tasarımı yanlıştır. Verimli logging ile saniyede yüz milyonlarca olay işlenebilir
  • Modern yazılımda tek bir log ile “ne oldu” sorusunu eksiksiz açıklamak zor.
    Bu yüzden dikey korelasyon (Vertical correlation) ve yatay korelasyon (Horizontal correlation) gerekir.
    Stack içindeki üst ve alt katmanlar aynı correlation değerini paylaşmalı; sistemler arası iletişimde de eşler arası korelasyon gerekir.
    Bu tür değerleri API’ye ya da protokole eklemek zor olabilir ama transaction ID önceden tasarlanırsa uçtan uca izleme mümkün olur

  • Tek bir yazı için ayrı bir domain kaydetmek bana pek sürdürülebilir gelmiyor.
    Her yıl yenileme ücreti ödemeniz gerekeceği için kişisel blog veya subdomain kullanmak daha iyi olabilir.
    Örneğin logging-sucks.boristane.com gibi bir yapı daha uygun

    • Aslında bu domain ve yazı, yazarın observability SaaS tanıtımı için var gibi. Cloudflare hesabı gerekiyor ama ücretsiz olduğu için uzun vadeli bir pazarlama hamlesi izlenimi veriyor. Yine de faydalıydı; bende de CF hesabı var, ben de denemeyi düşünüyorum
    • Bu yazı, Simon Willison’ın “Give people something to link to” yaklaşımıyla benzer bir bağlamda
    • Bu bir blog yazısından çok, dijital pazarlama amaçlı lead generation sayfasına benziyor. Servis tanıtımı oldukça açık
  • “Loglar monolitik çağın kalıntısıdır” iddiasına karşı, ben yerel logların hâlâ geçerli olduğunu düşünüyorum.
    Asıl rolleri yerel process’in konuşmalarını kaydetmektir; başka sunucularda neler olduğunu görmek için ise transaction tracing gerekir.
    Uygun noktadaki loglara bakmak çoğu zaman kök nedene ulaşmak için yeterlidir

    • Ama loglar yalnızca kök neden analizi için değildir; kimlerin etkilendiğini, performans ile girdi arasındaki ilişkiyi, güvenlik açıklarının etkisini gibi iş içgörüleri de verebilir.
      Zengin bağlam içeren loglar, analiz motorlarıyla birleşince ürün geliştirmede de kullanılabilir
    • “Bir istek 15 servis ve 3 veritabanından geçiyor” ifadesine karşı, böyle bir karmaşıklıktan zaten kaçınılması gerektiğini söyleyenler de vardı
    • Bana göre yalnızca APN/Kibana bile log analizi için yeterli olabiliyor
  • “Kodun ne yaptığını değil, isteğe ne olduğunu loglayın” sözüne katılıyorum ama yazar biraz deneyimsiz göründü.
    Ben buna “bug parts logging” diyorum ve işleme yolu, tekrar sayısı, süre gibi öncü sinyallerin de dahil edilmesi gerektiğini düşünüyorum.
    Logging, metrik ya da audit ile aynı şey değildir. Logging başarısız olsa da işleme devam etmelidir; ama audit başarısızlığı kritik olabilir.
    SCADA sistemlerindeki “historian” kavramında olduğu gibi, gözlemlenebilirler (observables) ile değerlendirmeler (evaluatives) ayrılmalıdır.
    Örneğin yakıt sensörünün ayrıntılı olayları tanı için yararlıdır ama “hedefe ulaşılabilir mi” sorusu için gerekli değildir.
    Sonuçta önemli olan, neyi gözlemleyeceğinizi ve neyi değerlendireceğinizi netleştirmektir

    • Ben **“birleşik gözlemlenebilirlik teorisi”**ni destekliyorum. Loglar, metrikler ve denetim kayıtları sonuçta birer bit akışıdır ve kayıpsız dönüştürülebilir.
      Depolama, dönüştürme ve sorgulama yöntemleri farklı olsa da, tüketim noktaları ve mekanizmaları aynı şekilde tasarlanabilir.
      Bu sayede sistem tasarımı sadeleşir ve uzun süre saklanan loglar daha sonra yeniden işlenebilir de olabilir