C# İle Özel Bir Loglama Sistemi İçin Interceptor Nasıl Yapılır?

C# İle Özel Bir Loglama Sistemi İçin Interceptor Nasıl Yapılır?
C# İle Özel Bir Loglama Sistemi İçin Interceptor Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu uygulamayı hayata geçirmek için geliştirme ortamınızın güncel olması gerekmektedir. Interceptor özelliği, C# derleyicisi (Roslyn) düzeyinde çalışan bir mekanizmadır. Bu nedenle projenizin .NET 8 veya .NET 9 SDK'sı ile yapılandırılmış olması gerekir.

  • SDK: .NET 8.0 veya üzeri.
  • IDE: Visual Studio 2022 (17.8+) veya JetBrains Rider.
  • Bilgi Seviyesi: C# Attributes (Nitelikler), Source Generators (Kaynak Üreticileri) ve Reflection kavramlarına aşinalık.

Interceptor'lar, derleme zamanında kodun belirli noktalarına müdahale ettiği için çalışma zamanı (runtime) maliyetini minimize eder. Bu, geleneksel Proxy tabanlı yaklaşımlara göre çok daha performanslı bir çözümdür.

Interceptor Nedir ve Nasıl Çalışır?

Interceptor, derleyicinin belirli bir metod çağrısını, sizin tanımladığınız başka bir metod ile değiştirmesine olanak tanıyan bir mekanizmadır. Normalde bir metod çağrıldığında derleyici doğrudan o metodun adresine gider. Interceptor ile derleyiciye, "Bu metodu gördüğünde, bunun yerine benim belirlediğim şu metodu çalıştır" talimatı veririz.

Bu yapı, özellikle loglama gibi tüm projeye yayılması gereken işlemlerde, geliştiricinin her metoda manuel olarak _logger.Log() yazmasını engeller. Bunun yerine, bir "Intercepting" katmanı üzerinden merkezi bir yönetim sağlarız.

Adım Adım Interceptor Yapılandırması

İlk adımda, hedef metodumuzu ve bu metodu yakalayacak olan interceptor sınıfımızı tanımlamalıyız. C#'ta bir metodun intercept edilebilmesi için System.Runtime.CompilerServices.InterceptsLocationAttribute niteliğinin kullanılması gerekir.


// Hedef metodumuz
public class OrderService
{
    public void ProcessOrder(string orderId)
    {
        Console.WriteLine($"Sipariş işleniyor: {orderId}");
    }
}

Yukarıdaki kod, normal bir iş akışını temsil eder. Şimdi, bu metoda müdahale edecek olan interceptor sınıfını oluşturalım. Dikkat etmeniz gereken en önemli nokta, interceptor metodunun imzasının (parametre tipleri, dönüş tipi) hedef metodla birebir aynı olması gerektiğidir.


using System.Runtime.CompilerServices;

public static class InterceptorLog
{
    [InterceptsLocation("C:\\Projeler\\App\\OrderService.cs", 5, 24)]
    public static void LogAndProcess(this OrderService service, string orderId)
    {
        Console.WriteLine($"[LOG]: {DateTime.Now} - Sipariş işlenmeden önce loglandı: {orderId}");
        service.ProcessOrder(orderId);
    }
}

Burada InterceptsLocation niteliği, dosya yolunu ve satır/sütun bilgilerini alır. Bu, derleyicinin hangi noktayı değiştireceğini tam olarak anlamasını sağlar.

Loglama Mantığının Entegre Edilmesi

Interceptor yapısını kurduktan sonra, içerisine loglama mantığını yerleştirmeliyiz. Burada dikkat edilmesi gereken nokta, loglama işleminin asıl işin performansını düşürmemesi için asenkron bir yapı kullanılmasıdır.


public static class LoggerInterceptor
{
    public static void LogExecution(string methodName, string parameters)
    {
        // Gerçek bir senaryoda burası bir veritabanına veya ELK stack'e yazabilir
        File.AppendAllText("log.txt", $"{DateTime.Now}: {methodName} çağrıldı. Parametreler: {parameters}\n");
    }
}

Bu yardımcı sınıf, loglama işlemini merkezi bir yerden yönetmemizi sağlar. Interceptor metodunuzun içinden bu sınıfı çağırarak, tüm süreç boyunca standart bir log formatı izleyebilirsiniz.

Karşılaştırmalı Analiz: Interceptor vs. Decorator

Yazılım mimarisinde loglama için farklı yöntemler mevcuttur. Aşağıdaki tablo, Interceptor yapısının diğer yöntemlere göre avantajlarını özetler.

Yöntem Avantajı Dezavantajı
Decorator Pattern Esneklik, arayüz tabanlı Çok fazla sınıf oluşturma (boilerplate)
Interceptor (C#) Yüksek performans, az kod Derleyici bağımlılığı, dosya yolu hassasiyeti
Middleware (ASP.NET) HTTP seviyesinde kolay Sadece web istekleri için uygun

Kritik Uyarılar ve Güvenlik

Güvenlik Uyarısı: Interceptor yapısı, derleme zamanında kodun çalışma şeklini değiştirdiği için dikkatli kullanılmalıdır. Özellikle üretim (production) ortamında, interceptor mantığınızda oluşabilecek bir hata, uygulamanın tamamının çökmesine neden olabilir. Loglama yaparken asla kullanıcı şifreleri, kredi kartı bilgileri veya kişisel verileri (PII) düz metin olarak loglamayın. Verileri maskeleyen bir mekanizma kullanın.

Yaygın Hatalar ve Debug İpuçları

Interceptor kullanırken en sık karşılaşılan hata, InterceptsLocation içindeki dosya yolu veya satır numarasının yanlış verilmesidir. Eğer derleyici hedefi bulamazsa, interceptor çalışmaz ve uygulama normal akışına devam eder.

Debug İpucu: Eğer interceptor'ınızın devreye girip girmediğini anlamak istiyorsanız, interceptor metodunun ilk satırına bir Console.WriteLine ekleyin. Eğer çıktı almıyorsanız, derleyici hedefi eşleştiremiyor demektir.


// Hata ayıklama için basit bir kontrol
[InterceptsLocation("...", 5, 24)]
public static void DebugInterceptor(this OrderService service, string orderId)
{
    System.Diagnostics.Debug.WriteLine("Interceptor tetiklendi!");
    service.ProcessOrder(orderId);
}

Bu yöntem, derleyicinin atamayı yapıp yapmadığını hızlıca doğrulamanızı sağlar.

Sıkça Sorulan Sorular

Interceptor her projede kullanılmalı mıdır?

Hayır, interceptor oldukça güçlü ancak karmaşık bir araçtır. Sadece performansın kritik olduğu ve merkezi bir loglama/izleme ihtiyacının bulunduğu büyük ölçekli sistemlerde tercih edilmelidir.

Interceptor ile asenkron metodları yakalayabilir miyim?

Evet, ancak metod imzasının Task veya ValueTask dönen metodlarla tam olarak eşleşmesi gerekir. Aksi takdirde derleme hatası alırsınız.

Performans üzerinde olumsuz bir etkisi var mı?

Tam tersine, reflection tabanlı çözümlerden çok daha hızlıdır çünkü derleme zamanında (compile-time) çözümlenir.

Interceptor'lar başka hangi alanlarda kullanılır?

Sadece loglama değil; yetkilendirme (authorization), önbellekleme (caching) ve performans metrikleri toplama gibi çapraz kesen sorumluluklarda kullanılır.

Dosya yolu değişirse ne olur?

Interceptor'lar dosya yoluna bağımlı olduğu için, kaynak kodda yapılan büyük değişiklikler (metodun yerinin değişmesi gibi) interceptor'ın bozulmasına neden olur. Bu yüzden Source Generator ile birlikte kullanılması önerilir.

İleri Seviye İpucu: Source Generator ile Otomasyon

Manuel [InterceptsLocation] tanımlamaları, özellikle büyük projelerde yönetilmesi zor bir hale gelebilir. Dosya yollarının veya satır numaralarının değişmesi, interceptor'larınızın sessizce devre dışı kalmasına neden olabilir. Bu sorunu aşmak için Roslyn Source Generator kullanarak, derleme zamanında (compile-time) hedef metodları otomatik olarak tespit eden bir yapı kurabilirsiniz.

Source Generator, kodunuzu analiz ederek gerekli öznitelikleri ve dosya yollarını sizin yerinize oluşturur. Böylece manuel hata payını sıfıra indirirsiniz. Aşağıdaki örnek, bir metodun imzasını analiz edip interceptor için gerekli olan dosya yolunu dinamik olarak çıkaran temel bir yapı mantığını göstermektedir:

[Generator]
public class InterceptorGenerator : ISourceGenerator
{
    public void Execute(GeneratorExecutionContext context)
    {
        // Derleme zamanında metodları tara ve 
        // [InterceptsLocation] özniteliğini içeren dosyayı üret
        string source = @"
        namespace GeneratedInterceptors {
            public static class AutoGenerated {
                [System.Runtime.CompilerServices.InterceptsLocation(""C:\\Proje\\Service.cs"", 10, 12)]
                public static void InterceptedMethod() { }
            }
        }";
        context.AddSource("Interceptor.g.cs", source);
    }

    public void Initialize(GeneratorInitializationContext context) { }
}

Üretim Ortamında Performans İzleme ve Optimizasyon

Interceptor'lar, her metod çağrısında ekstra bir katman oluşturduğu için yüksek trafikli sistemlerde CPU kullanımını artırabilir. Loglama sisteminizin darboğaz yaratmaması için aşağıdaki optimizasyon stratejilerini uygulamanız önerilir:

  • Asenkron Loglama: Log kayıtlarını doğrudan disk veya veritabanına yazmak yerine, bir Channel veya BlockingCollection kullanarak arka plan iş parçacığına devredin.
  • Koşullu Loglama: Interceptor içerisinde metot çalışmadan önce bir "log seviyesi" kontrolü yaparak, gereksiz işlemlerin önüne geçin.
  • Bellek Yönetimi: Log nesnelerini oluştururken ArrayPool veya ObjectPool kullanarak Garbage Collector üzerindeki yükü azaltın.

Aşağıdaki tablo, loglama stratejilerinin performans üzerindeki etkisini özetlemektedir:

Strateji Performans Etkisi Güvenilirlik
Senkron Yazma Düşük (Bloklayıcı) Yüksek
Asenkron Kuyruk Yüksek Orta (Kuyruk dolarsa veri kaybı riski)
Fire-and-Forget Çok Yüksek Düşük
Profesyonel Not: Interceptor'ları sadece "Cross-Cutting Concerns" (loglama, caching, validation) için kullanın. İş mantığını (business logic) interceptor içine taşımak, kodun okunabilirliğini ciddi oranda düşürecek ve hata ayıklamayı imkansız hale getirecektir.

Sonuç

C# ile özel bir loglama sistemi için interceptor kullanmak, kod kalitenizi ve izlenebilirliğinizi bir üst seviyeye taşıyacaktır. Bu rehberde öğrendiğiniz temel yapıları, projenizin ihtiyaçlarına göre özelleştirebilirsiniz. Unutmayın ki, en iyi interceptor, iş mantığını bozmadan arka planda sessizce çalışan interceptor'dır.

Bir sonraki adım olarak, InterceptsLocation manuel tanımlamaları yerine, C# Source Generator kullanarak bu öznitelikleri otomatik üreten bir kütüphane oluşturmayı deneyebilirsiniz. Bu, kodunuzun sürdürülebilirliğini ve hata toleransını ciddi oranda artıracaktır.

Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında kullanmadan önce güvenlik testlerinden geçirilmeli ve loglama politikalarınızın KVKK/GDPR uyumunu kontrol etmelisiniz.

Bu yazıya tepkinizi paylaşın:
Zeynep Arslan

Mutfak pratikleri ve ev düzeni konularında yıllardır içerik üretiyorum. Okuyuculara zaman kazandıran, uygulanabilir ve sürdürülebilir yaşam tarzı önerileri sunuyorum.

Yorumlar (0)

Yorum Yaz