Gereksinimler ve Ön Hazırlık
Uygulamayı geliştirmek için .NET 8 veya 9 SDK yüklü bir geliştirme ortamına ihtiyacınız vardır. Veritabanı yönetim sistemi olarak Microsoft SQL Server kullanacağız. Projenizde Entity Framework Core (EF Core) paketlerinin yüklü olduğundan emin olun.
- Visual Studio 2022 veya VS Code
- .NET 8/9 SDK
- Entity Framework Core NuGet paketleri
- SQL Server Management Studio (SSMS)
Projenizi oluşturduktan sonra, NuGet paket yöneticisi konsolundan şu komutları çalıştırarak gerekli bağımlılıkları ekleyin:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Design
Veritabanı Log Tablosunun Tasarlanması
Loglama sisteminin temeli, tutulan verilerin düzenli bir şekilde saklandığı bir tablodur. "AuditLogs" adında bir tablo oluşturarak, her işlemin kimliğini, tablosunu, işlem türünü (Insert, Update, Delete) ve eski/yeni değerlerini saklayacağız.
public class AuditLog
{
public int Id { get; set; }
public string TableName { get; set; }
public string Action { get; set; } // Insert, Update, Delete
public string OldValues { get; set; } // JSON formatında
public string NewValues { get; set; } // JSON formatında
public DateTime ChangeDate { get; set; } = DateTime.UtcNow;
public string UserId { get; set; }
}
Bu model sınıfı, veritabanındaki her değişikliği izlemek için kullanılacak temel yapıdır. JSON formatında veri saklamak, veritabanı şemasını her tablo değişikliğinde güncelleme zorunluluğunu ortadan kaldırır.
DbContext Üzerinde SaveChanges Metodunu Özelleştirme
EF Core'da veritabanına yapılan her kayıt işlemi SaveChanges metodu üzerinden geçer. Bu metodu override ederek, veritabanına gitmeden hemen önce değişiklikleri yakalayabilir ve log tablosuna yazabiliriz.
public override async Task SaveChangesAsync(CancellationToken cancellationToken = default)
{
var auditEntries = OnBeforeSaveChanges();
var result = await base.SaveChangesAsync(cancellationToken);
await OnAfterSaveChanges(auditEntries);
return result;
}
Bu yöntem, "Interception" (araya girme) mantığıyla çalışır. İşlem gerçekleşmeden önce verinin durumunu alır, işlem bittikten sonra ise logları kalıcı hale getirir.
Değişiklikleri İzleme ve JSON Serileştirme
Hangi verilerin değiştiğini tespit etmek için ChangeTracker sınıfını kullanırız. Aşağıdaki kod bloğu, Entity'nin durumunu analiz eder ve değişen alanları JSON olarak hazırlar.
private List OnBeforeSaveChanges()
{
ChangeTracker.DetectChanges();
var auditEntries = new List();
foreach (var entry in ChangeTracker.Entries())
{
if (entry.Entity is AuditLog || entry.State == EntityState.Detached || entry.State == EntityState.Unchanged)
continue;
var auditEntry = new AuditEntry(entry)
{
TableName = entry.Metadata.GetTableName(),
Action = entry.State.ToString()
};
auditEntries.Add(auditEntry);
}
return auditEntries;
}
Bu adım, uygulamanın performansını doğrudan etkiler. Çok sayıda verinin güncellendiği durumlarda, ChangeTracker üzerindeki yükü optimize etmek için sadece izlenmesi gereken tabloları filtreleyebilirsiniz.
Loglama Stratejileri Karşılaştırması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| EF Core Interceptor | Merkezi ve otomatik | Karmaşık sorgularda performans kaybı |
| Database Trigger | Veritabanı seviyesinde garanti | Koddan bağımsız, yönetimi zor |
| Repository Pattern | Kontrollü ve esnek | Her metoda manuel ekleme gerektirir |
Güvenlik ve Performans Uyarıları
Kritik Uyarı: Loglama sistemleri, hassas verileri (şifreler, kredi kartı bilgileri) asla düz metin olarak saklamamalıdır. Log verilerini serileştirirken, "Password" veya "Secret" içeren alanları filtrelediğinizden emin olun. Ayrıca, log tablosunun aşırı büyümesini önlemek için periyodik temizleme (archiving) stratejileri uygulayın.
Sıkça Sorulan Sorular
Loglama sistemi uygulamayı yavaşlatır mı?
Evet, her kayıtta ek bir veritabanı işlemi yapıldığı için küçük bir gecikme yaşanabilir. Bunu aşmak için loglama işlemlerini asenkron (async) olarak arka planda kuyruğa alarak çalıştırabilirsiniz.
Log verilerini nasıl şifrelemeliyim?
Veritabanı seviyesinde "Transparent Data Encryption" (TDE) kullanabilir veya uygulama katmanında veriyi serileştirmeden önce AES gibi simetrik şifreleme algoritmalarıyla şifreleyebilirsiniz.
Hangi tabloları loglamalıyım?
Sadece kritik verilerin olduğu (Kullanıcılar, Siparişler, Finansal kayıtlar) tabloları loglamanız önerilir. Tüm tabloları loglamak disk alanını hızla tüketir.
Log tablosu silinirse ne olur?
Log tablosu, ana veritabanı operasyonundan bağımsız bir işlem olarak tasarlanmalıdır. Hata durumunda loglama başarısız olsa bile ana işlem devam etmelidir (Try-Catch blokları ile yönetilmelidir).
Logları nasıl raporlayabilirim?
Log verileri JSON formatında olduğu için, bunları bir "Log Viewer" arayüzü ile okumak için Newtonsoft.Json veya System.Text.Json kütüphanelerini kullanarak kolayca deserialize edebilirsiniz.
Loglama Sistemlerinde Hata Ayıklama ve İzlenebilirlik
Loglama mekanizmalarınızın düzgün çalışıp çalışmadığını doğrulamak, sistemin güvenilirliği için kritiktir. Özellikle karmaşık ilişkisel verilerde (Entity Framework Core ile 1-N veya N-N ilişkiler), ChangeTracker üzerinden yakalanan veriler bazen beklenenden farklı sonuçlar verebilir. Hata ayıklama sürecinde şu adımları izlemek, sistemin sağlığını korumanıza yardımcı olur:
- Log Kayıtlarını Doğrulama: Loglama işlemini gerçekleştiren
SaveChangesAsyncmetodunuzun içine birtry-catchbloğu ekleyerek, loglama sırasında oluşabilecek veritabanı hatalarının ana işlemi (business logic) kesmesini engelleyin. - Kullanıcı Bağlamını İzleme: Log kayıtlarına mutlaka
UserIdveyaRequestIDgibi tanımlayıcılar ekleyin. Bu, bir hata anında hangi kullanıcının hangi işlemi tetiklediğini takip etmenizi sağlar.
public override async Task SaveChangesAsync(CancellationToken cancellationToken = default)
{
try
{
return await base.SaveChangesAsync(cancellationToken);
}
catch (DbUpdateException ex)
{
// Loglama hatasını ayrı bir dosyaya veya konsola yazdırın
Console.WriteLine($"Loglama sırasında hata oluştu: {ex.Message}");
throw;
}
}
Performans Optimizasyonu İçin Asenkron Loglama
Veritabanı loglama işlemleri, özellikle yüksek trafikli uygulamalarda ana veritabanı üzerinde yük oluşturabilir. Performans kaybını minimize etmek için loglama işlemlerini ana işlemden ayırmak (decoupling) en iyi yaklaşımdır. Bu noktada Background Service veya Message Queue (RabbitMQ, Azure Service Bus) kullanımı önerilir.
Eğer veritabanı üzerinde doğrudan loglama yapıyorsanız, log tablonuzun indeksleme stratejisini gözden geçirmeniz gerekir. CreatedDate veya EntityName gibi sık sorgulanan kolonlar üzerinde indeks oluşturmak, raporlama hızınızı ciddi oranda artıracaktır.
| Strateji | Avantaj | Dezavantaj |
|---|---|---|
| Senkron Loglama | Veri tutarlılığı garantidir. | İstek süresini uzatır. |
| Asenkron/Background Loglama | Performans kaybı minimumdur. | Hata durumunda log kaybı riski olabilir. |
İleri Düzey İpucu: Log Verilerini Arşivleme
Log tabloları zamanla milyonlarca satıra ulaşabilir. Bu durum veritabanı performansını düşürür. Belirli bir süreden (örneğin 6 ay) eski logları otomatik olarak bir "LogArchive" tablosuna veya düşük maliyetli bir depolama birimine (Blob Storage gibi) taşıyan bir Hangfire görevi tanımlamak, sisteminizin uzun vadeli sürdürülebilirliği için hayati önem taşır.
// Hangfire ile örnek bir temizleme görevi
RecurringJob.AddOrUpdate(() => ArchiveOldLogs(), Cron.Monthly);
public void ArchiveOldLogs()
{
var threshold = DateTime.Now.AddMonths(-6);
var oldLogs = _context.AuditLogs.Where(x => x.CreatedAt < threshold).ToList();
// Verileri arşiv tablosuna taşı ve ana tablodan sil
_context.AuditLogs.RemoveRange(oldLogs);
_context.SaveChanges();
}
Sonuç
C# ile profesyonel bir veritabanı kayıt loglama sistemi oluşturmak, uygulamanızın izlenebilirliğini ve güvenliğini bir üst seviyeye taşır. Bu rehberde öğrendiğiniz DbContext override yöntemleri ve ChangeTracker kullanımı, kurumsal projelerin vazgeçilmez bir parçasıdır. Bir sonraki adım olarak, bu logları merkezi bir log sunucusuna (Elasticsearch veya Serilog gibi) göndererek daha gelişmiş analizler yapabilirsiniz.
Yasal Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamında kullanmadan önce güvenlik açıklarını (SQL Injection, XSS) göz önünde bulundurarak gerekli testleri yapınız. Veri gizliliği yasalarına uygunluk sağlamak, geliştiricinin sorumluluğundadır.


Yorumlar (0)
Yorum Yaz