Gereksinimler ve Ön Hazırlık
Windows servislerinde hata takibi yapmak için modern .NET ekosisteminde en güvenilir yöntem Serilog kütüphanesini kullanmaktır. Serilog, yapılandırılmış loglama (structured logging) desteği ile hataları sadece metin olarak değil, sorgulanabilir veriler olarak kaydetmenizi sağlar.
- Visual Studio 2022 veya üzeri sürüm.
- .NET 8.0 veya .NET 9.0 SDK.
- NuGet üzerinden:
Serilog.Extensions.Hosting,Serilog.Sinks.FileveSerilog.Sinks.EventLogpaketleri.
Projenizi oluştururken "Worker Service" şablonunu seçmeniz, Windows servisi olarak çalışacak temel yapıyı otomatik olarak kurmanızı sağlar.
Adım 1: Serilog Kütüphanesinin Kurulumu
Servis projenize gerekli kütüphaneleri eklemek için NuGet Paket Yöneticisi Konsolu'nu kullanabilirsiniz. Bu kütüphaneler, logların hem yerel bir dosyaya hem de Windows Olay Görüntüleyicisi'ne (Event Viewer) yazılmasını sağlar.
Install-Package Serilog.Extensions.Hosting
Install-Package Serilog.Sinks.File
Install-Package Serilog.Sinks.EventLog
Bu paketler, uygulamanızın loglama altyapısını merkezi bir noktadan yönetmenize olanak tanır. Özellikle Sinks.File, fiziksel bir dosya üzerinde hata geçmişini tutarken, Sinks.EventLog sistem yöneticilerinin Windows araçlarıyla logları incelemesine imkan verir.
Adım 2: Program.cs İçinde Loglama Yapılandırması
Servisiniz ayağa kalkarken loglama motorunu başlatmanız gerekir. Program.cs dosyasında CreateHostBuilder (veya modern .NET'te Host.CreateApplicationBuilder) içerisinde Serilog'u konfigüre ederek servisin yaşam döngüsü boyunca hataları yakalamasını sağlayın.
using Serilog;
var builder = Host.CreateApplicationBuilder(args);
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.File("logs/servis-hatalari.txt", rollingInterval: RollingInterval.Day)
.WriteTo.EventLog("ServisUygulamasi", manageEventSource: true)
.CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(Log.Logger);
Buradaki RollingInterval.Day parametresi, log dosyalarının her gün otomatik olarak yeni bir isimle (tarih bazlı) oluşturulmasını sağlar. Bu, dosya boyutunun kontrolsüz büyümesini engeller.
Adım 3: Servis İçinde Hata Yakalama (Try-Catch Blokları)
Servisinizin ana döngüsü (ExecuteAsync) içerisinde oluşabilecek hataları yakalamak için ILogger arayüzünü kullanmalısınız. Dependency Injection (Bağımlılık Enjeksiyonu) sayesinde logger nesnesini sınıfınıza dahil edin.
public class Worker : BackgroundService
{
private readonly ILogger _logger;
public Worker(ILogger logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
// İş mantığınız burada yer alır
await DoWork();
}
catch (Exception ex)
{
_logger.LogError(ex, "Servis çalışırken kritik bir hata oluştu: {Message}", ex.Message);
}
await Task.Delay(10000, stoppingToken);
}
}
}
LogError metodu, hatanın yığın izini (stack trace) otomatik olarak log dosyasına yazar. Bu, hatanın kodun hangi satırında oluştuğunu tespit etmek için en önemli veridir.
Adım 4: Loglama Yöntemlerinin Karşılaştırılması
Windows servislerinde hata loglama için kullanabileceğiniz farklı yaklaşımlar vardır. İhtiyacınıza göre en uygun yöntemi seçmelisiniz.
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Metin Dosyası | Hızlı erişim, basit yapı | Büyük dosyalarda yavaş okuma |
| Windows Event Log | Sistem entegrasyonu | Kısıtlı veri boyutu |
| Veritabanı Loglama | Gelişmiş sorgulama | Bağlantı hatasında log yazılamaz |
Adım 5: Güvenli Loglama Uygulamaları
Kritik Uyarı: Log dosyalarına asla kullanıcı şifreleri, kredi kartı bilgileri veya kişisel verileri (KVKK kapsamındaki veriler) yazmayın. Log dosyaları genellikle düz metin olarak saklanır ve yetkisiz erişimlere karşı savunmasız olabilir.
Hassas verileri maskelemek, loglama sisteminizin güvenliği için şarttır. Aşağıdaki örnek, loglama sırasında veriyi nasıl maskeleyeceğinizi gösterir.
public void LogUserAction(string username, string password)
{
// Şifreyi asla loglamayın, maskeleyin
string maskedPassword = "****";
_logger.LogInformation("Kullanıcı işlemi: {User}, Şifre: {Pass}", username, maskedPassword);
}
Adım 6: Hata Loglarını Test Etme ve İzleme
Servisin hata logladığından emin olmak için bir "test hatası" tetikleyebilirsiniz. Servis çalışırken kasıtlı bir throw new Exception() komutu çalıştırarak log dosyasının güncellenip güncellenmediğini kontrol edin.
private async Task DoWork()
{
// Test amaçlı hata fırlatma
throw new InvalidOperationException("Bu bir test hatasıdır.");
}
Testten sonra logs/servis-hatalari.txt dosyasını açın. Dosya içerisinde hatanın zaman damgası, hata tipi ve yığın izinin detaylıca yazıldığını görmelisiniz.
Sıkça Sorulan Sorular
Log dosyalarım çok büyüyor, ne yapmalıyım?
Serilog konfigürasyonunda retainedFileCountLimit parametresini kullanarak eski logların otomatik silinmesini sağlayabilirsiniz. Ayrıca dosya boyutu limitlerini (fileSizeLimitBytes) belirleyerek dosyayı parçalayabilirsiniz.
Loglar Windows Event Viewer'da görünmüyor, neden?
Servisin çalıştığı kullanıcı hesabının "Event Log" yazma yetkisi olmayabilir. Servisi "LocalSystem" veya "NetworkService" yerine uygun yetkilere sahip bir hesapla çalıştırın veya manageEventSource: true seçeneğinin aktif olduğundan emin olun.
Loglama performansı etkiler mi?
Evet, her log satırı disk I/O işlemi demektir. Çok yoğun servislerde asenkron loglama (Serilog.Sinks.Async) kullanarak performans kaybını minimize edebilirsiniz.
Hataları e-posta ile bildirebilir miyim?
Evet, Serilog.Sinks.Email paketini kullanarak kritik hatalarda (Error seviyesinde) otomatik e-posta gönderimi yapılandırabilirsiniz.
Log seviyeleri (Information, Warning, Error) neyi ifade eder?
Information genel akışı, Warning potansiyel sorunları, Error ise servisin çalışmasını engelleyen veya veri kaybına yol açan kritik hataları temsil eder. Loglarınızı bu seviyelere göre filtreleyerek yönetmelisiniz.
İleri Seviye: Merkezi Log Yönetimi ve Seq Entegrasyonu
Windows servisleriniz arttıkça, her sunucuya tek tek bağlanıp metin tabanlı log dosyalarını okumak imkansız hale gelir. Bu noktada, loglarınızı merkezi bir sunucuya göndermek operasyonel verimliliği artırır. Seq, .NET ekosistemi için yapılandırılmış loglama konusunda endüstri standardı haline gelmiş bir araçtır.
Seq Kullanarak Logları Görselleştirme
Serilog'un Serilog.Sinks.Seq paketini kullanarak, hatalarınızı anlık olarak bir arayüze aktarabilirsiniz. Bu sayede hataları kategorize edebilir ve belirli bir hata türü için alarm kurabilirsiniz.
// NuGet: Serilog.Sinks.Seq
// Program.cs içerisindeki yapılandırmayı güncelleyin:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Seq("http://localhost:5341") // Seq sunucu adresiniz
.CreateLogger();
Bu yapılandırma ile servisiniz, hata oluştuğu anda veriyi JSON formatında Seq sunucusuna iletir. Böylece "Hata oluştuğunda bana mail at" gibi karmaşık kuralları kod yazmadan, Seq arayüzü üzerinden tanımlayabilirsiniz.
Windows Servislerinde Performans Odaklı Loglama Stratejileri
Loglama işlemleri, özellikle yüksek trafikli servislerde I/O (girdi/çıktı) darboğazına neden olabilir. Servisinizin ana iş mantığını (business logic) yavaşlatmamak için "Asenkron Loglama" yöntemini kullanmanız kritiktir.
Asenkron Loglama ile Servis Hızını Koruma
Serilog'un Serilog.Sinks.Async paketini kullanarak log yazma işlemlerini ayrı bir arka plan iş parçacığına (thread) devredebilirsiniz. Bu, uygulamanızın logun diske yazılmasını beklemeden bir sonraki işleme geçmesini sağlar.
// NuGet: Serilog.Sinks.Async
// Yapılandırmayı asenkron sarmalayıcı ile güncelleyin:
Log.Logger = new LoggerConfiguration()
.WriteTo.Async(a => a.File("logs/servis-log-.txt", rollingInterval: RollingInterval.Day))
.CreateLogger();
Performans İçin İpuçları:
- Log Seviyesi Filtreleme: Üretim (Production) ortamında
DebugveyaVerboseseviyelerini kapatın. SadeceInformationve üstünü kaydedin. - Batching (Toplu Yazma): Çok sayıda log üretiliyorsa, bunları tek tek değil, belirli aralıklarla veya belirli bir boyuta ulaştığında toplu olarak diske yazan "Batching" özellikli sink'leri tercih edin.
- Disk I/O İzleme: Servisinizin kurulu olduğu sunucuda disk yazma hızlarını (Performance Monitor üzerinden) takip ederek, loglama işleminin disk üzerinde bir kuyruk oluşturup oluşturmadığını kontrol edin.
Profesyonel İpucu: Eğer servisiniz çok kritik veriler işliyorsa, loglama işleminin başarısız olması durumunda uygulamanın çökmemesi için SelfLog özelliğini mutlaka aktif edin. Bu, Serilog'un kendi içinde oluşan hataları (örneğin disk dolması) Windows Event Viewer'a yazmasını sağlar.
// Serilog'un kendi hatalarını izlemek için:
Serilog.Debugging.SelfLog.Enable(msg => Console.Error.WriteLine(msg));
Sonuç
C# ile Windows servisi geliştirmek, hata yönetimi ile birleştiğinde profesyonel bir çözüme dönüşür. Bu rehberde, Serilog kullanarak nasıl sürdürülebilir, güvenli ve izlenebilir bir loglama sistemi kuracağınızı öğrendiniz. Bir sonraki adım olarak, loglarınızı merkezi bir log sunucusunda (Elasticsearch veya Seq gibi) toplayarak daha büyük ölçekli analizler yapmayı deneyebilirsiniz.
Yasal Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Yazılım güvenliği, uygulamanızın çalıştığı ağ altyapısına ve sunucu yapılandırmasına göre değişiklik gösterir. Üretim ortamına almadan önce tüm kodları güvenlik testlerinden geçirmeniz önerilir.


Yorumlar (0)
Yorum Yaz