Mert Özen Her Satırda Daha İleri
Backend .NET Core Web API — #27

Health check ve monitoring: API'nin ayakta ve sağlıklı olduğunu izlemek

Mert Özen 23 Ağu 2026 12 dk 26 görüntülenme
Health check ve monitoring: API'nin ayakta ve sağlıklı olduğunu izlemek

Health check ve monitoring'i işliyoruz: uygulamanın canlıda sağlıklı olup olmadığını otomatik kontrol etmek, veritabanı gibi bağımlılıkları izlemek, liveness/readiness ayrımı ve monitoring'in temel fikri.

API'n artık doğru çalışıyor ve hızlı. Ama canlıya çıktıktan sonra yeni bir soru belirir: o an gerçekten ayakta mı? Veritabanına ulaşabiliyor mu, yoksa sessizce mi çökmüş? Bunu öğrenmek için birinin şikâyet etmesini beklemek kötü bir stratejidir. İyi bir uygulama, sağlığını kendisi bildirir. Bugün health check ve monitoring'i konuşuyoruz: API'ni sadece çalışır değil, aynı zamanda izlenebilir kılmanın yollarını.

Neden Health Check Gerekli?

Bir uygulama canlıda çalışırken pek çok şey ters gidebilir: veritabanı bağlantısı kopar, bağımlı olduğu bir servis cevap vermez, disk dolar. Bu durumlarda uygulama görünüşte "çalışıyor" olabilir ama aslında iş göremez haldedir. Sorun şu ki, bunu dışarıdan anlamak zordur; ta ki bir kullanıcı hata alıp şikâyet edene kadar. O noktaya geldiğinde ise iş işten geçmiştir.

Health check'i bir hastanedeki hasta monitörü gibi düşün. Hastanın kalp atışını, nabzını, oksijenini sürekli ölçer ve bir değer normalin dışına çıktığında anında alarm verir. Kimse hastanın "kendini kötü hissettiğini söylemesini" beklemez; monitör sorunu daha o fark etmeden yakalar. Health check de uygulamana bunu yapar: sürekli "iyi misin?" diye sorar ve bir sorun olduğunda erkenden haber verir.

En Basit Health Check

.NET, health check'i yerleşik olarak destekler. En basit haliyle kurmak iki satır. Önce servisi kaydedersin:

builder.Services.AddHealthChecks();

Sonra bunu bir endpoint olarak yayınlarsın:

app.MapHealthChecks("/health");

Artık uygulaman /health adresinde basit bir sağlık raporu sunuyor. Bu adrese bir istek attığında, her şey yolundaysa "Healthy" cevabı ve 200 durum kodu döner. Uygulama ayakta değilse bu adrese hiç ulaşılamaz; ayaktaysa ama bir sorun varsa sağlıksız bir cevap döner. Bu endpoint'in asıl kullanıcısı insanlar değil, otomatik sistemlerdir; birazdan buna geleceğiz.

Bağımlılıkları Kontrol Etmek

Basit health check sadece "uygulama ayakta mı?" sorusuna cevap verir. Ama gerçek bir uygulamanın sağlığı, bağlı olduğu şeylerin sağlığına da bağlıdır. Uygulaman çalışıyor olabilir ama veritabanına ulaşamıyorsa, aslında iş göremez durumdadır. İşte bu yüzden health check'ler, bağımlılıkları da kontrol edecek şekilde zenginleştirilir.

Örneğin veritabanının erişilebilir olup olmadığını kontrol eden bir health check ekleyebilirsin. .NET ekosisteminde bunun için hazır paketler var; veritabanı, Redis gibi yaygın bağımlılıkları kontrol eden hazır kontroller sunarlar. Fikir şu: sağlık raporu artık sadece "uygulama nefes alıyor mu?" demez, "uygulama gerçekten iş yapabilir durumda mı, ihtiyaç duyduğu her şeye ulaşabiliyor mu?" der. Yirmi altıncı yazıda eklediğimiz Redis'i de bu kontrole dahil edebilir, "cache'im ayakta mı?" sorusunu da izleyebilirsin.

İki Farklı Soru: Liveness ve Readiness

Health check'lerde önemli bir ayrım var, bunu bilmek işine çok yarayacak. Aslında iki farklı soru soruyoruz ve bunlar karıştırılmamalı.

Liveness (canlılık): "Uygulama hayatta mı?" Yani süreç çalışıyor mu, yoksa tamamen çökmüş mü? Eğer bu kontrol başarısız olursa, çözüm genelde uygulamayı yeniden başlatmaktır.

Readiness (hazır olma): "Uygulama iş almaya hazır mı?" Uygulama ayakta olabilir ama henüz veritabanı bağlantısını kuramamış ya da başlangıç işlemlerini bitirememiş olabilir. Bu durumda hayattadır ama iş alacak durumda değildir.

Bu ayrım neden önemli? Çünkü çözümleri farklıdır. Bir uygulama hayatta ama hazır değilse, onu yeniden başlatmak sorunu çözmez; sadece hazır olmasını beklemek gerekir. Ama tamamen çökmüşse, yeniden başlatmak doğru harekettir. Bu iki kontrolü ayrı ayrı yaparak, otomatik sistemlerin doğru kararı vermesini sağlarsın. .NET, health check'leri etiketleyerek bu ikisini ayırmana izin verir.

Bu Bilgiyi Kim Kullanıyor?

/health endpoint'ini kimin çağırdığını merak ediyor olabilirsin. Cevap: otomatik sistemler. İki tipik kullanıcısı var. Birincisi, uygulamanı çalıştıran altyapı (mesela yirmi dokuzuncu yazıda değineceğimiz konteyner ortamları). Bu sistemler /health adresini düzenli aralıklarla yoklar; sağlıksız cevap alırsa uygulamayı yeniden başlatabilir ya da o örneğe trafik göndermeyi durdurabilir.

İkincisi, izleme (monitoring) araçlarıdır. Bunlar /health endpoint'ini sürekli kontrol eder ve bir sorun tespit ettiğinde ilgili kişilere alarm gönderir; bir e-posta, bir mesaj, bir bildirim. Böylece sen gece uyurken bile, veritabanı bağlantısı koptuğunda telefonun titrer ve daha kullanıcılar fark etmeden müdahale edebilirsin.

Monitoring: Sağlıktan Fazlası

Health check, "iyi misin?" sorusunun anlık cevabıdır. Monitoring ise daha geniş bir kavram: uygulamanın zaman içindeki davranışını sürekli gözlemlemektir. Sadece "ayakta mı?" değil, "ne kadar hızlı cevap veriyor, kaç istek alıyor, hata oranı ne, bellek kullanımı nasıl?" gibi soruların cevabını da sürekli toplarsın.

On dördüncü yazıda loglamayı konuşurken bu kültürün temelini atmıştık; monitoring, o fikrin bir üst katmanıdır. Loglar sana "ne oldu?" sorusunun cevabını verirken, monitoring "genel gidişat nasıl, bir eğilim var mı?" sorusunu cevaplar. İkisi birlikte, uygulamanın canlıdaki hayatına dair tam bir görünürlük sağlar. Bu görünürlüğe genel olarak "observability" yani gözlemlenebilirlik denir: sistemin içinde ne olup bittiğini dışarıdan anlayabilme yeteneği.

Küçük Bir Deneme

Projene önce en basit health check'i ekle ve /health adresine giderek "Healthy" cevabını gör. Sonra bunu zenginleştir: veritabanı bağlantısını kontrol eden bir health check ekle. Uygulamayı çalıştır ve /health'in artık veritabanının durumunu da yansıttığını gözlemle. Ardından bilerek bir sorun yarat; mesela veritabanı bağlantı bilgisini geçici olarak boz ve /health'in nasıl "Unhealthy" döndüğünü gör. Bu küçük deney, health check'in soyut bir kavram değil, uygulamanın nabzını tutan somut bir araç olduğunu net biçimde gösterir.

Bir sonraki yazıda uygulamayı dağıtmaya hazırlanıyoruz. İlk adım Docker olacak: uygulamayı, her yerde aynı şekilde çalışacak taşınabilir bir pakete nasıl koyacağımızı konuşacağız. "Benim makinemde çalışıyordu" cümlesini tarihe gömmenin zamanı geliyor. Bugün eklediğimiz health check, o konteyner ortamında tam olarak işe yarayacak.