Postsharp Kullanarak Metot Execution Sürelerini Hesaplama

Daha önceki aspect oriented yazılarımızda ne aspect oriented'ın ne olduğunu ve nasıl kullanıldığını çeşitli örneklerle anlatmıştık ve AOP yaklaşımı ile yapılabileceklerin sınırının olmadığından bahsetmiştik. Bu yazımızda da özellikle server-side geliştirme yapanların sıkça ihtiyaç duyduğu metot execution süresinin AOP yaklaşımı ile nasıl yapıldığından bahsedeceğiz. 

Yazılımda performans bildiğiniz üzre en önemli konuların başında gelir ve büyük çapta 1 den fazla client'ın consume ettiği bir projeniz var ise metot execution sürelerini bir yerlerde logluyor olmak bizler için şu gibi durumlarda hayat kurtarıcı bir rol üstlenir; client der ki "Abi sayfa 8 saniyede açılıyor bizde bir sıkıntı yok service'den geç geliyor....vs.", server-side'da geliştirme yapan arkadaşta der ki "Yok abi ben 0.2 saniyede response dönmüşüm bu bizden değil...vs.". Bu gibi durumlarda eğer siz service olarak projenizden eminseniz bu durumu kanıtlamak için en güzel çözüm metot execution sürelerini hesaplayıp delil olarak ilgili mercilere sunmak. Ya da bu case'i de geçelim bizler developerlar olarak kendimize "arkadaş bi proje yaptık ama işler nasıl gidiyor, yazılımsal olarak performansı yerinde mi.." vs. gibi soruları sorup cevaplarını da biliyor olmamız gerekir.

Bunun için AOP çözümlerinden biri olan Postsharp'dan yararlanacağız. Case şu şekilde olacak; Bir Api projemiz olsun ve MoneyTransfer adında eft-havale-virman işlemlerini yapan end-point geliştirelim ve bu end-point'e gelen request-response'ların execution sürelerini LoggingAspect kullanarak loglayalım.

*PostSharp kurulumu vs bilgileri için şu yazıyı inceleyebilirsiniz.

    [Serializable]
    public class LoggingAspect : OnMethodBoundaryAspect
    {
        private readonly Stopwatch timer = new Stopwatch();  

        public override void OnEntry(MethodExecutionArgs args)
        {
            timer.Start();
        }

        public override void OnExit(MethodExecutionArgs args)
        {
           var executionTime = timer.ElapsedMilliseconds;
            timer.Stop();
            var logMessage = "Method : " args.Method.Name +  " Execution Time : " + executionTime + " Millisecond";
            Console.Write(logMessage );
        }
    }

Sırada MoneyTransfer işlemi yapan metodu yazalım ve bu metot parametre olarak TransferRequest objesi alsın ve response olarak TransferResponse adında bir model dönsün.

        [LoggingAspect]
        public TransferResponse MoneyTransfer(TransferRequest request)
        {
            // back-end kodlarınız

            var resp = new TransferResponse
            {
                IsSuccess = true,
                Message = "Transfer İşleminiz Gerçekleşti."
            };
            return resp;
        }

        public class TransferRequest
        {
            public decimal Amount { get; set; }
            public string SenderIBAN { get; set; }
            public string ReceiverIBAN { get; set; }
        }

        public class TransferResponse
        {
            public bool IsSuccess { get; set; }
            public string Message { get; set; }
        }
    }

Hepsi bu kadar artık yazdığımız kodları test edebiliriz. TransferMoney metoduna request yolladığımızda metot scope'ları içerisindeki kodları run etmeden aspect'imiz içerisinde bulunan OnEntry metoduna girecektir ve burada timer'ı start ediyoruz. Sonrasında metot scope'ları içerisinde bulunan kodları çalıştırıp metottan çıktıktan sonra OnExit metoduna girip timer'ı stop edip devamında execution süresini millisecond cinsinden Console'a yazacaktır.

Metot execution süresi yukarıda da belirttiğim gibi önemli bir konudur ve ne nerde ne kadar süre harcayıp client'a gidiyor bunu ölçeklendirebiliyor olmak gerekir.

Not: Çok uzun süren execution sürelerinin çok büyük bir ihtimalle networksel sorunlardan dolayı kaynaklanabileceği ihtimalini de unutmamak gerekir.

Comments (1) -

  • Merhaba, değerli yorumun  için teşekkürler.
    Haklısın stopWatch nesnesini static olarak bu şekilde kullanımı doğru değil, kullanılıyorsa da reset() metodu çağrılmalı ancak bu örneği geliştirdiğim projede IoC container'da vardı ve bu aspect container'a perRequest başına instance oluşturacak şekilde register edilmişti bu sebeple ben geliştirmeyi yaparken belirttiğin soruna denk gelmedim. Tekrardan  yorumun için teşekkürler.

Add comment