Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması

Merhaba,

Birçoğumuz uygulamalarımızın gelişim süreçlerinde oldukça titiz davranmaya çalışmakta ve yeni ihtiyaçlara istinaden mümkün mertebe ilgili uygulamanın gelişime açık bir şekilde inşa edilmesine özen göstermekteyiz, öyle değil mi? Peki ya yayın süreçlerinde uygulamamızın ne durumda olduğuna dair neler gerçekleştirmekteyiz? Çoğunuzun bu soruya ‘log mekanizmaları’ cevabını vererek dibine kadar doğru bir öneride bulunduğunuzu biliyorum. Evet, haklısınız. Uygulamanın yayın sürecinde sergilediği davranışları derinlemesine bilgi aktarımında bulunduğumuz log mekanizmalarıyla takip ederek, adım adım kendimize göre metrikler oluşturup nerede ne olmuş rahatlıkla bilebilmekteyiz. Ama bu log mekanizmaları uygulama çalıştığı sürece geçerli olacak bir evrenin parçası değil midir? Nasıl yani?🧐 dediğinizi duyar gibiyim. Yani demek istediğim, log mekanizmaları uygulama çalıştığı sürece bizlere takip edilebilir kayıtlar sağlamaktadırlar. Halbuki bir uygulamanın yayın sürecinde yaşadıkları logların alabileceğiyle sınırlı değildir! Misal olarak; uygulama sunucusu çalışmıyor olabilir veya uygulamanın beslendiği veritabanı sunucusuna erişim sağlanamıyor da olabilir ya da kullanılan Redis yahut RabbitMQ gibi kritik sorumluluk üstlenen harici sunucularda da arızalar söz konusu da olabilir. Böyle durumlar uygulama açısından log mekanizmasını aşan hayati bir krizle pençeleşildiğinin alametidir diyebiliriz. İşte bu durumlara istinaden, yukarılarda ilk satırlarda sorduğumuz soruyu tekrar edersek eğer cevap olarak uygulamanın genel sağlığını kontrol etmemizi sağlayacak bir monitoring(izleme) sisteminin inşa edilmesi olmazsa olmaz bir gerekliliktir diyebilir miyiz? Evet, dibine kadar deriz 🙂 Haliyle bizler bu içeriğimizde Asp.NET Core uygulamalarında monitoring amaçlı özel olarak geliştirilmiş olan Health Check mekanizmasına derinlemesine bakış atacak ve konuyu yapısal olarak ele alabilmek için pratikte dockerize edilmiş servisler üzerinde nasıl bir yaklaşım sergilenmesi gerektiğine dair somut bir örnek eşliğinde seyrediyor olacağız. O halde fazla uzatmadan buyrun başlayalım…

Neden Uygulamalarımızı Monitoring Etmeliyiz?

İlk olarak bu sorunun cevabını vererek başlayalım. Nasıl ki insanlar, sağlık durumları için periyodik olarak doktor muayenesinden geçiyorlarsa benzer mantıkla yayın sürecindeki yazılımlar içinde bu periyodik muayene kesinlikle olmazsa olmazlardandır. Nihayetinde yazılımlar da tıpkı insanlar gibi canlı bir organizmadır ve süreç içerisinde farklı sebeplerden dolayı krizler, çöküşler ve hatta ölümler yaşayabilmektedirler. Bu sebepler, bir üstteki paragrafta saydığımız birkaç hususla beraber ayriyeten kontrolsüz bellek kullanımından doğan sıkıntılar, yetersiz disk alanından kaynaklı çöküşler vs. olabilmektedirler. İşte bu tarz işlevselliği sonlandırıcı durumları yönetebilmek için öncelikle bu durumlardan haberdar olmamız gerekmektedir. Bunun için ilgili yazılımların ne durumda olduğu bilgisini veren api’lar oluşturulmalı ve bu api’ları dinleyerek bizlere görsel veri sağlayan monitoring yapıları kullanılmalıdır. Böylece anlık olarak yazılımlar üzerinde oluşabilecek durumları daha dinamik takip edebilme ve gerektiği taktirde alınması gereken aksiyonları fazla kayba ve maliyete mahal vermeksizin alabilecek fırsatı kendimize sağlamış olmalıyız.

Asp.NET Core Health Check Nedir? Neden Bunu Tercih Etmeliyiz?

Yukarıda monitoring’in öneminden bahsettik. Eğer ki, Asp.NET Core mimarisinde bir yazılım yahut servis geliştiriyorsanız hızlı bir şekilde Health Check özelliğiyle sağlık kontrolü yapabileceğiniz bir mekanizma oluşturabilir ve bunu monitoring edebilirsiniz. Health Check mekanizması, ilgili yazılımın sağlık durumuna dair bilgi verirken bu işlemi uygulamadaki iş kuralı gereği devreye sokulmuş middleware’leri ve log mekanizmalarını tetiklemeksizin gerçekleştirmektedir. İşte bu özellik ilgili mekanizmanın etkisini kat be kat arttırmaktadır. Nihayetinde bizler bir uygulamanın ayakta olup olmadığını kontrol edebilmek için herhangi bir api’sini tetiklediğimizde Asp.NET Core mimarisinin pipeline’ı devreye girecek ve sonuç dönene kadar devreye sokulmuş olan tüm middleware’ler bir yandan tetiklenirken bir yandan da varsa log mekanizması çalışıp ilgili tabloya lüzumsuz bir kayıt eklenecektir. Oysa Asp.NET Core Health Check mekanizması sayesinde tüm middleware ve log yapıları es geçilip direkt uygulamanın sağlığı check edilecek ve duruma göre bilgi döndürülecektir. Böylece ateşi çıkmış bir çocuğun ateşini ölçmek için nasıl ki lüzumsuz yere dişlerini yahut kulaklarını kontrol etmeksizin direkt ateşini ölçüyorsak benzer mantıkla sağlık kontrolü yapılacak yazılımında farklı noktalarını tetiklemeksizin direkt sağlık kontrolünü nokta atış sağlamış oluyoruz. Muazzam değil mi?

Bir Asp.NET Core Uygulamasında Health Check Nasıl Uygulanır?

Bu makale içeriğinin büyük bölümü bu sorunun cevabını detaylandırmakla geçecektir. Haliyle şimdi yavaş yavaş konuya pratikten giriş yaparak ele almaya başlayabiliriz.

Bir Asp.NET Core uygulaması üzerinde Health Check mekanizması en sade haliyle aşağıdaki konfigürasyonlar eşliğinde etkinleştirilebilmektedir.(Bu uygulamanın adını ‘Service1’ olarak veriyorum)

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();
var app = builder.Build();
app.UseHealthChecks("/health");
app.Run();

Yukarıdaki kod bloğunu incelerseniz, uygulamaya 2. satırda olduğu gibi AddHealthChecks servisinin eklenmesi ve ardından 4. satırda olduğu gibi UseHealthChecks middleware’inin tetiklenmesi yeterlidir. UseHealthChecks middleware’ine dikkat ederseniz eğer parametre olarak “/health” değeri verilmektedir. Bu değer işlevsel olarak bu uygulamanın sağlık kontrolünü yapabilmemizi sağlayacak olan health check mekanizmasının endpoint’ini ayarlamamızı sağlamaktadır ve tercihinize göre değişkenlik gösterebilmektedir.

Böylece artık bu uygulamada health check mekanizması aktifleştirilmiştir ve https://localhost:7188/health adresine yapılacak istek neticesinde ilgili yazılımın sağlık durumuna dair bilgi dönebilecek durumdadır.

Uygulamayı derleyip, ayağa kaldırarak ilgili adrese istek gönderdiğimizde aşağıdaki gibi ‘Healthy’ mesajıyla karşılaşacağız.Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring UygulamasıHealth check neticesinde ‘Healthy’ ile birlikte ‘Unhealthy’ ve ‘Degraded’ olmak üzere alabileceğimiz üç farklı durum bilgisi mevcuttur.

  • Healthy, yazılımın problemsiz çalıştığını ifade eder.
  • Unhealthy, yazılımın çalışma sürecinde bazı problemlerin var olduğunu ifade eder. İnceleme gerektirir.
  • Degraded, yazılımın problemsiz ama cevap süresinin olağandan daha fazla olduğunu ifade etmektedir.

Peki bu health check mekanizmasıyla sadece yazılımın sağlığını mı kontrol ediyoruz?
Tabi ki de hayır! Yazılımın kullandığı veritabanı sunucusundan tutun da Redis, RabbitMQ, EventStore ve hatta SignalR connection’ına kadar aklınıza gelebilecek birçok sunucuların sağlık durumlarını check edebilmekteyiz.

Bunun için kontrol edilecek sunucuya uygun olan paketi yüklemeniz gerekmektedir.

Install-Package AspNetCore.HealthChecks.System
Install-Package AspNetCore.HealthChecks.Network
Install-Package AspNetCore.HealthChecks.SqlServer
Install-Package AspNetCore.HealthChecks.MongoDb
Install-Package AspNetCore.HealthChecks.Npgsql
Install-Package AspNetCore.HealthChecks.Elasticsearch
Install-Package AspNetCore.HealthChecks.CosmosDb
Install-Package AspNetCore.HealthChecks.Solr
Install-Package AspNetCore.HealthChecks.Redis
Install-Package AspNetCore.HealthChecks.EventStore
Install-Package AspNetCore.HealthChecks.AzureStorage
Install-Package AspNetCore.HealthChecks.AzureServiceBus
Install-Package AspNetCore.HealthChecks.AzureKeyVault
Install-Package AspNetCore.HealthChecks.Azure.IoTHub
Install-Package AspNetCore.HealthChecks.MySql
Install-Package AspNetCore.HealthChecks.DocumentDb
Install-Package AspNetCore.HealthChecks.SqLite
Install-Package AspNetCore.HealthChecks.RavenDB
Install-Package AspNetCore.HealthChecks.Kafka
Install-Package AspNetCore.HealthChecks.RabbitMQ
Install-Package AspNetCore.HealthChecks.IbmMQ
Install-Package AspNetCore.HealthChecks.OpenIdConnectServer
Install-Package AspNetCore.HealthChecks.DynamoDB
Install-Package AspNetCore.HealthChecks.Oracle
Install-Package AspNetCore.HealthChecks.Uris
Install-Package AspNetCore.HealthChecks.Aws.S3
Install-Package AspNetCore.HealthChecks.Consul
Install-Package AspNetCore.HealthChecks.Hangfire
Install-Package AspNetCore.HealthChecks.SignalR
Install-Package AspNetCore.HealthChecks.Kubernetes
Install-Package AspNetCore.HealthChecks.Gcp.CloudFirestore
Install-Package AspNetCore.HealthChecks.SendGrid
Install-Package AspNetCore.HealthChecks.ArangoDb
Install-Package AspNetCore.HealthChecks.Gremlin

Misal olarak, bizim yukarıda oluşturduğumuz servis varsayalım ki MS SQL ve Redis kullanıyor olsun. Haliyle bunlarla ilgili paketleri uygulamaya yükledikten sonra aşağıdaki çalışmanın yapılması gerekmektedir.

İlgili paketler : AspNetCore.HealthChecks.SqlServer, AspNetCore.HealthChecks.Redis

builder.Services
    .AddHealthChecks()
    .AddSqlServer(builder.Configuration.GetConnectionString("MSSQLServer"))
    .AddRedis(builder.Configuration.GetConnectionString("Redis"));

Görüldüğü üzere AddHealthChecks fonksiyonu üzerinden AddSqlServer ve AddRedis servislerini ekleyerek health check mekanizmasında MS SQL Server ve Redis sunucularının da kontrol edilmesi gerektiği bildirilmiştir.Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring UygulamasıTüm sunucular ayaktayken ‘Healthy’ cevabı alınırken, Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulamasıherhangi birine erişilmediği taktirde ‘Unhealthy’ cevabı alınmaktadır.

Buradan anlayacağımız health check mekanizması gayet güzel bir şekilde çalışmaktadır.

Ayrıca şunu söylemekte de fayda vardır ki, her bir health check amaçlı sunucu servisi eklendiğinde aşağıdaki gibi name, tags, failure status vs. gibi bilgiler de desteklenebilmektedir.

builder.Services
    .AddHealthChecks()

    .AddSqlServer(
    connectionString: builder.Configuration.GetConnectionString("MSSQLServer"),
    healthQuery: "SELECT 1",
    name: "MS SQL Server Check",
    failureStatus: HealthStatus.Unhealthy | HealthStatus.Degraded,
    tags: new string[] { "db", "sql", "sqlserver" })

    .AddRedis(
    redisConnectionString: builder.Configuration.GetConnectionString("Redis"),
    name: "Redis Check",
    failureStatus: HealthStatus.Unhealthy | HealthStatus.Degraded,
    tags: new string[] { "redis" });

Yukarıdaki kod bloğunda olduğu gibi konfigürasyonları ayarlarsak eğer “/health” adresine yapılan istek neticesinde aşağıdaki gibi sonuçla karşılaşılmaktadır.Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring UygulamasıTabi bu sonucu alabilmek için UseHealthChecks middleware’ine aşağıdaki gibi HealthCheckOptions parametresi eklenerek ‘ResponseWriter’ property’sine UIResponseWriter.WriteHealthCheckUIResponse değeri verilmelidir. Tabi burada UIResponseWriter sınıfına erişebilmek için AspNetCore.HealthChecks.UI.Client paketinin yüklenmesi gerektiğini söylemekte fayda vardır kanaatindeyim.

var app = builder.Build();
app.UseHealthChecks("/health", new HealthCheckOptions
{
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});

Asp.NET Core Health Check UI Kullanımı

Health check sayesinde ilgili yazılım(lar)a dair alınan sağlık bilgilerinin sonuçlarını depolayarak görselleştirilmesini sağlayan hazır kullanıcı arayüzü mevcuttur. Bu arayüzü kullanabilmek için birkaç satır önce bahsi geçen AspNetCore.HealthChecks.UI paketinin yüklenmesi gerekmektedir. Tabi, anlık olarak görselliği destekleyecek verilerin bir storage’da depolanması gerekmektedir. Bu storage; In-Memory, Sql Server, SQLite, PostgreSQL yahut MySQL olabilir. Haliyle bu storagelar’dan ihtiyacınıza binaen istediğinizi aşağıdaki kütüphanelerden karşılayabilirsiniz:

Şimdi UI yapılanmasını örneklendirmeye geçmeden önce bunun için ayrı bir servis oluşturulmasının best practices açısından daha doğru olacağını bilmenizde fayda vardır. Nihayetinde birden fazla servisten gelecek olan sağlık bilgilerini tek bir arayüz eşliğinde takip etmek isteyebilirsiniz, ki isteyeceksiniz de 🙂 Bu sebepten dolayı yeni bir Asp.NET Core uygulaması üzerinden aşağıdaki konfigürasyonları sağlayalım(Bu uygulamanın adını ‘MonitoringService’ olarak veriyorum):

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddHealthChecksUI(settings =>
settings.AddHealthCheckEndpoint("Service 1", "https://localhost:7188/health"))
    .AddSqlServerStorage(connectionString: builder.Configuration.GetConnectionString("MonitoringSQLServer"));

var app = builder.Build();

app.UseHealthChecksUI(options => options.UIPath = "/health-ui");

app.Run();

Yukarıdaki kod bloğuna göz atarsanız eğer, 3 ile 6. satır aralığında Health Check UI arayüzünün konfigürasyonu yapılmaktadır. AddHealthChecksUI fonksiyonu ile arayüz servisi uygulamaya eklenmekte ve bu metot içerisinde parametre olarak verilen lambda üzerinden AddHealthCheckEndpoint fonksiyonu eşliğinde metrikleri görselleştirilecek endpoint verilmektedir. Dikkat ederseniz verilen endpoint, içeriğimizin önceki satırlarında oluşturduğumuz servisimizin “/health” endpoint’idir. Burada dinlenecek tüm endpoint’leri AddHealthCheckEndpoint metodu eşliğinde seri bir şekilde verebiliriz. Bununla ilgili sonraki satırlarımızda çalışma yapıyor olacağız.

6. satırda ise AddSqlServerStorage fonksiyonu ile servislerin durumlarına dair verileri tutacağımız storage entegrasyonu gerçekleştirilmektedir. Buradan anlaşıldığı üzere ben deniz SQL Server’ı storage olarak benimsemiş bulunuyorum. Sizler yukarıdaki satırlarda bahsi geçen storage’lardan istediğinizi aşağıdaki formatlarda kullanabilirsiniz.
In-Memory:

  services
    .AddHealthChecksUI()
    .AddInMemoryStorage();

PostgreSQL:

  services
    .AddHealthChecksUI()
    .AddPostgreSqlStorage("connectionString");

MySQL:

  services
    .AddHealthChecksUI()
    .AddMySqlStorage("connectionString");

Sqlite:

  services
    .AddHealthChecksUI()
    .AddSqliteStorage($"Data Source=sqlite.db");

Son olarak 10. satıra göz atarsanız eğer UseHealthChecksUI middleware’i çağrılarak arayüz etkinleştirilmiş ve ‘UIPath’ property’si aracılığıyla “/health-ui” adresinden erişilebilir hale getirilmiştir.

Velhasıl… İlgili uygulamayı bu vaziyette derleyip, ayağa kaldırırsak eğer connection string’i verilen storage’a, arayüze dair verileri tutacağı veritabanı ve tabloları direkt olarak aşağıdaki görselde olduğu gibi migrate edecektir.
Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring UygulamasıElbet bu tabloların neye yaradığını sonraki satırlarımızda açıklayacağız. Şimdilik oluşturduğumuz monitoring arayüzünün çalışıp çalışmadığını test edelim istiyorum. Tabi bunun için hem ‘Service1’ hem de ‘MonitoringService’ ayağa kaldırılmalıdır. Kaldırıldığını varsayalım ve ardından ‘MonitoringService’in https://localhost:7033/health-ui adresine tarayıcı üzerinden istek gönderip, açalım.
Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring UygulamasıBakın, görüldüğü üzere ilgili servisimiz ve kullandığı sunucular gayet sağlıklı.
Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring UygulamasıÇünkü sunucularımız gayet problemsiz çalışıyor. Misal, herhangi bir sunucuda sıkıntı olduğunu varsayarsak eğer aşağıdaki görseldeki gibi uyarıyla karşılaşılacaktır.
Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring UygulamasıAsp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması

Tabi buradaki örneklendirmeleri sizler paralel bir şekilde icra ediyorsanız eğer sunuculardaki problemlerin arayüz tarafından hemen algılanmadığını göreceksiniz. Çünkü Health Check UI mekanizmasının servisleri yoklama süresi default olarak 10 saniyedir. Sizler ihtiyaç doğrultusunda bu süreye aşağıdaki konfigürasyonla müdahale edebilirsiniz.

builder.Services
    .AddHealthChecksUI(settings =>
    {
        settings.AddHealthCheckEndpoint("Service 1", "https://localhost:7188/health");
        settings.SetEvaluationTimeInSeconds(5);
    })

Görüldüğü üzere SetEvaluationTimeInSeconds fonksiyonu ile servislerin saniye cinsinden ne kadar periyotta bir değerlendirileceği belirtilebilmektedir.

Ayrıca servislerdeki health check adreslerine olabilecek aşırı isteklerden kaçınmak için maksimum etkin istek sayısını aşağıdaki gibi SetApiMaxActiveRequests metodu aracılığıyla yapılandırabilirsiniz. Bu özelliğin defualt değeri 3’tür.

builder.Services
    .AddHealthChecksUI(settings =>
    {
        settings.AddHealthCheckEndpoint("Service 1", "https://localhost:7188/health");
        settings.SetApiMaxActiveRequests(2);
    })

Health Check UI yapılanmasını kullanıyorsak eğer migration özelliğini de yönetebilmemiz gerekmektedir. Varsayılan olarak etkin olan migration yapılanmasını yeri gelir kapatma ihtiyacı yahut isteği hissedebilirsiniz. İşte böyle bir durumda aşağıdaki iki yöntemden birini tercih edebilirsiniz;

1. Yöntem:

builder.Services
    .AddHealthChecksUI(settings =>
    {
        .
        .
        .
        settings.DisableDatabaseMigrations();
    })

Bu yöntemde AddHealthChecksUI fonksiyonu içerisinde DisableDatabaseMigrations metodunun çağrılması yeterlidir.

2. Yöntem;

  "HealthChecksUI": {
    "DisableMigrations": true
  }

Bu yöntemde ise uygulamanın ‘appsettings.json’ dosyasına yukarıdaki konfigürasyon değerlerinin eklenmesi gerekir.

Hangi yöntemi kullanırsanız kullanın uygulama ayağa kaldırılırken migration’lar etkin olmadığı için storage sunucusuna herhangi bir veritabanı ve tablo migrate edilmeyecektir.

Health Check UI Veritabanı Tablolarını İnceleyelim

Health Check UI veritabanı tablolarının ne olduğunu izah edebilmek için konuyu zenginleştirebilmek adına öncelikle yeni bir servis ekleyelim isterim. Monitoring edilen servis sayısı ne kadar fazla olursa UI veritabanındaki tabloların görevini daha net görebileceğiz kanaatindeyim. Haliyle aşağıdaki gibi ‘MongoDb’ ve ‘RabbitMQ’ sunucularını kontrol eden bir servis oluşturalım(Bu uygulamanın adını ‘Service2’ olarak veriyorum)

using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddHealthChecks()

    .AddMongoDb(
    mongodbConnectionString: "mongodb://localhost:27017",
    name: "Mongo Db Check",
    failureStatus: HealthStatus.Unhealthy | HealthStatus.Degraded,
    tags: new string[] { "mongodb" })

    .AddRabbitMQ(
    rabbitConnectionString: "amqp://admin:123456@localhost:5672",
    name: "RabbitMQ Check",
    failureStatus: HealthStatus.Unhealthy | HealthStatus.Degraded,
    tags: new string[] { "rabbitmq" });

var app = builder.Build();

app.UseHealthChecks("/health", new HealthCheckOptions
{
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});

app.Run();

Ardından bu servisinde endpoint’ini ‘MonitoringService’e aşağıdaki gibi ekleyelim.

builder.Services
    .AddHealthChecksUI(settings =>
    {
        settings.AddHealthCheckEndpoint("Service 1", "https://localhost:7188/health");
        settings.AddHealthCheckEndpoint("Service 2", "https://localhost:7169/health");
    })

Yapılan konfigürasyonlar neticesinde arayüzümüzün son durumu aşağıdaki gibi olacaktır.
Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring UygulamasıŞimdi Health Check UI’ın veritabanındaki tablolarının davranışlarını daha rahat gözlemleyebiliriz.Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması

  • Configurations Tablosu
    Tasarımı İşlevi
    Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması Health Check UI’ın sağlık kontrolü amaçlı tükettiği servislere dair bilgileri tutan tablodur.
    Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması
  • Executions Tablosu
    Tasarımı İşlevi
    Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması Servislerin hangi tarihten itibaren ve son olarak ne zaman sağlık durumlarının kontrol edildiğini tutan tablodur.
    Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması

  • Failures Tablosu
    Tasarımı İşlevi
    Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması Sağlık durumunda problem olan servis bilgilerini tutan tablodur. Dikkat edilmesi gereken nokta hatanın kaynağı ne olursa olsun sadece servis bilgilerini tutmaktadır.
    Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring UygulamasıMisal olarak, ‘Service 2’nin kullandığı ‘RabbitMQ’ sunucusuna erişim kapatıldığı taktirde ‘Failures’ tablosuna ‘Service 2’de bir hata olduğuna dair yukarıdaki gibi kayıt düşecektir.

    Servis’te ki problem çözüldüğü taktirde ilgili servise dair ‘IsUpAndRunning’ kolonu ‘1’ değerinde olacak şekilde servisin tam olarak çalıştığını ifade eden bir kayıt düşülecektir.

  • HealthCheckExecutionEntries Tablosu
    Tasarımı İşlevi
    Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması Servislerde sağlık kontrolü yapılan sunucuları ve bilgilerini tutan tablodur.
    Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması
  • HealthCheckExecutionHistories Tablosu
    Tasarımı İşlevi
    Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması Servislerde sağlık kontrolü yapılan sunuculardaki olası hataların kaydını tutan tablodur.
    Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring UygulamasıSunuculardaki problem çözüldüğü taktirde ilgili sunucuya ait ‘Status’ değeri ‘2’ olan ve ‘Description’ı ‘NULL’ olan ve böylece çalıştığını ifade eden yeni bir kayıt atılmaktadır.

Health Check Geçmiş Zaman Çizelgesi

Health Check UI, sağlık kontrolü yapılan sunucuların geçmiş sağlık zaman çizelgelerini sunmaktadır. Bunun için ilgili sayfada ‘Details’ butonuna tıklanması yeterlidir.
Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması
Misal olarak; ‘Service 2’nin kullanmış olduğu ‘RabbitMQ’ sunucusunun zaman çizelgesini görüntülediğimizde yandaki gibi bir görüntüyle karşılaşılmaktadır. Haliyle bu hizmet sayesinde bizler servis ve sunucularımızın geçmişine dair teferruatlı bilgiler alabilmekte ve ne zaman, hangi tarihte ne gibi problemler yaşayıp tekrardan çözüm getirildiğini görebilmekteyiz.

Esasında bu zaman çizelgesindeki verilerin, veritabanındaki ‘HealthCheckExecutionHistories’ tablosundan geldiğinin farkındasınızdır. Dolayısıyla bir sunucu geçmişine dair herhangi bir veriyi temizlemek veritabanına manuel müdahale yapılmadığı sürece fiziksel olarak mümkün değildir. Bu sebepten dolayı arayüzde gösterilecek maksimum geçmiş bilgilerini sınırlandırmak için aşağıdaki konfigürasyonu kullanabilirsiniz:

builder.Services
    .AddHealthChecksUI(settings =>
    {
        .
        .
        .
        settings.MaximumHistoryEntriesPerEndpoint(5);
    })

MaximumHistoryEntriesPerEndpoint fonksiyonu sayesinde geçmiş zaman çizelgesinden gelecek veriyi sınırlandırabilirsiniz.

Konfigürasyonları appsettings.json Dosyasına Taşınması

Şuana kadar anlatılan tüm konfigürasyonlar kodun içerisinden gerçekleştirildiği gibi ‘appsettings.json’ üzerinden de aşağıdaki formatla sağlanabilmektedir.

{
  .
  .
  .
  "HealthChecksUI": {
    "HealthChecks": [
      {
        "Name": "Service 1",
        "Uri": "https://localhost:7188/health"
      },
      {
        "Name": "Service 2",
        "Uri": "https://localhost:7169/health"
      },
      {
        "Name": "Service 3",
        "Uri": "..."
      }
    ],
    "Webhooks": [
      {
        "Name": "",
        "Uri": "",
        "Payload": "",
        "RestoredPayload": ""
      }
    ],
    "EvaluationTimeInSeconds": 5,
    "MinimumSecondsBetweenFailureNotifications": 60
  }
  .
  .
  .
}

Yapılandırma sürecini ‘appsettings.json’ üzerinden yönetmeyi tercih etmenizi öneririm. Hem daha dinamik hem de best practices açısından daha elverişlidir.

Health Check UI Tasarım Özelleştirmesi

Default gelen tasarımı pek beğenmemiş olabilir ya da iç açıcı bulamayabilirsiniz. Bu durumda aşağıdaki formatta bir css dosyası hazırlayıp belirtilen şekilde yapılandırmayla tasarımı customize edebilirsiniz.

:root {
    --primaryColor: #68217a;
    --secondaryColor: #f4f4f4;
    --bgMenuActive: #8e47a0;
    --bgButton: #68217a;
    --logoImageUrl: url('https://upload.wikimedia.org/wikipedia/commons/thumb/e/e3/.NET_Foundation_Logo.svg/1200px-.NET_Foundation_Logo.svg.png');
    --bgAside: var(--primaryColor);
}
app.UseHealthChecksUI(options =>
{
    options.UIPath = "/health-ui";
    options.AddCustomStylesheet("dotnet.css");
});

Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması

HttpClient Nesnesinin Yapılandırılması

Health Check UI mekanizması, servislerin sağlık durumlarını kontrol edebilmek için saniye cinsinden belirtilen periyotta bir servis endpoint’lerine Http isteği göndermektedir. Bazen, health check yaparken kimlik doğrulama vs. gibi işlemlerin yapılması gerekebilir. İşte böyle durumlar için arkaplanda kullanılan HttpClient nesnesini aşağıdaki gibi yapılandırabilirsiniz.

builder.Services
    .AddHealthChecksUI(settings =>
    {
        settings.ConfigureApiEndpointHttpclient((serviceProvider, httpClient) =>
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "...");
        })
        .ConfigureWebhooksEndpointHttpclient((serviceProvider, httpClient) =>
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "...");
        });
    })

Health Check Verilerini Yapılandırılmış Tüketicilere Göndermek

Health Check mekanizması, toplayabildiği verileri Application Insights, Datadog, Prometheus ve Seq gibi yapılandırılmış veri görselleştirici tüketicilere gönderebileceği bir push modeli içermektedir. Bunun için ilgili tüketiciye özel aşağıdaki paketlerden herhangi birinin veya birilerinin projeye yüklenmesi gerekmektedir.

Misal olarak; ‘Service 1’de ‘Redis’ sucunusunun hata aldığını varsayarsak bunu ‘Seq’ sunucusuna aşağıdaki gibi gönderebilir ve veriyi görselleştirebiliriz.

builder.Services
    .AddHealthChecks()
    .AddSqlServer(...)
    .AddRedis(...)
    .AddSeqPublisher(options =>
    {
        options.ApiKey = "vruCdRqaQUT4CeRXEJMw";
        options.Endpoint = "http://localhost:5341";
        options.DefaultInputLevel = HealthChecks.Publisher.Seq.SeqInputLevel.Information;
    }, "Service 1"));

Asp.NET Core Uygulamalarında Health Check İle Derinlemesine Monitoring Uygulaması

Nihai olarak;
Geliştirilen yazılımlarımızın yayın süreçlerindeki davranışlarını, tıpkı çocuklarımızın oyun parkındaki durumları gibi gözümüzü ayırmaksızın izlemeli ve gerektiği taktirde anlık müdahalede bulunabilir bir şekilde teyakkuzda olmalıyız 🙂 Aksi taktirde gecikilmiş olası problemlere karşı bizleri maliyeti bol durumlar bekliyor olabilir.

Ve böylece uzun ve meşakkatli olan bir yazımızın daha sonuna gelmiş bulunmaktayız. Sabredip okuduğunuz için teşekkür ederim.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımızda görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

2 Cevaplar

  1. Tarik dedi ki:

    Harika

  1. 31 Ağustos 2022

    […] yenisini ekleyebilirsiniz.Statping aracılığıyla özellikle .NET temelli servislerde Health Check özelliği ile kurulan monitoring yapılanmasını daha az maliyette hızlı ve pratik inşa […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir