İlkay İlknur

.NET Core Uygulamalarını dotnet-counters İle Monitor Etmek Ve Custom EventCounter Tanımlama

Ağustos 20, 2020

Bu yazıda .NET Core uygulamalarını monitör ederken kullanabileceğimiz .NET Core 3.0 ile beraber gelen dotnet-counters isimli araçtan bahsedeceğiz. dotnet-counters aracı basit olarak EventCounter API'ı üzerinden gönderilen counterları okumamızı veya saklamamızı sağlayan bir araç. EventCounter API'ları windows tarafında kullandığımız performance counterların aslında cross-platform versiyonu. EventCounter üzerinden istediğimiz metriği cross platform olarak loglayabiliriz. Böylece uygulamalarımızda bir problem olduğunda kolayca dotnet-counters aracını çalıştırıp sorunla ilgili ilk araştırmaları yapmamız mümkün hale gelmekte.

dotnet-counters aracını aşağıdaki komutu kullanarak yükleyebiliriz.

dotnet tool install --global dotnet-counters

Aracı global olarak yükledikten sonra dotnet-counters ps komutuyla monitor edebileceğimiz dotnet processlerini listeleyebiliriz.

Monitör etmek istediğimiz processi bulduktan sonra aşağıdaki komutla loglanan counterları terminalde görebiliriz.

dotnet-counters monitor --process-id <PID>

Bu komutu çalıştırdığımızda uygulamamızda desteklenen tüm counterların çıktılarını göremeyebiliriz. Bu nedenle ilk olarak desteklenen counterları belirleyip sonrasında monitor komutunu çalıştırmak daha doğru olacaktır.

Providerlara göre gruplu olarak counterları listelemek için aşağıdaki komutu kullanabiliriz.

dotnet-counters list

Sonrasında işimize yarayacak olan counterları bulduktan sonra monitor komutunu counter listesi vererek kullanabiliriz. Örneğin Microsoft.AspNetCore.Hosting counterlarını listelemek istersek.

dotnet-counters monitor --process-id <PID> --counter-list Microsoft.AspNetCore.Hosting

Monitor komutunu kullanırken belirtebileceğimiz son parametre ise refresh interval. Refresh interval'ı belirterek counterların kaç saniyede bir güncellenerek ekranda gösterileceğini belirtebilirsiniz.

dotnet-counters monitor --process-id <PID> --refresh-interval <seconds>

dotnet-counters aracıyla topladığımız verileri terminalde görüntülemek yerine daha sonra incelemek adına dosyaya da kaydedebiliriz. Bunun için de dotnet-counters collect komutunu kullanabiliriz. Bu komutu kullanırken monitor komutundaki parametrelere ek olarak dosyayı hangi formatta saklayacağını ve dosyanın adının ne olacağını belirtmemiz gerekiyor.

dotnet-counters collect --process-id <PID> --format <json|csv> --output <fileName>

Custom EventCounter Tanımlama

dotnet-counters aracını kullanırken ASP.NET Core veya kullandığımız kütüphanelerin sağladığı event counterları görüntülemenin yanı sıra kendi yazdığımız counterları da monitör edebilmemiz mümkün. Bunun için öncelikle bir EventSource tanımlaması yapıp, sonrasında da içerisine ilgili metriği loglayabiliriz.

[EventSource(Name = "MyCustomSource")]
public class MyEventSource : EventSource
{
    public static MyEventSource Instance = new MyEventSource();
 
    private EventCounter counter;
    public MyEventSource()
    {
        counter = new EventCounter("custom-counter"this);          
    }
 
    public void Log()
    {
        counter.WriteMetric(1);
    }
}

Metriklerin loglanmasını da bir action filter üzerinden tetikleyebiliriz.

public class CustomFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        MyEventSource.Instance.Log();
        base.OnActionExecuted(context);
    }
}

EventCounter tipi metric loglarken kullanabileceğimiz en temel tip. Bu tipi kullanarak loglanan değerlerin ortalaması dotnet-counters'da gösterilmekte. Bunun yanında IncrementingEventCounter, IncrementingPollingCounter, PollingCounter tiplerini kullanarak loglama operasyonlarını gerçekleştirebiliriz.

Son olarak bir örnek yaparsak diyelim ki custom bir API'ımız var ve biz bu API'a bir saniyede gelen request sayısını görmek istiyoruz. Bunun için şu şekilde EventCounter kullanımı yapabiliriz.

[EventSource(Name = "MyCustomSource")]
public class MyEventSource : EventSource
{
    public static MyEventSource Instance = new MyEventSource();
 
    private IncrementingPollingCounter counter;
    private long totalRequestCount;
    public MyEventSource()
    {
        counter = new IncrementingPollingCounter("weather-api-request-rate"this, () => totalRequestCount)
        {
            DisplayRateTimeScale = TimeSpan.FromSeconds(1),
 
        };
    }
 
    public void Log()
    {
        Interlocked.Increment(ref totalRequestCount);
    }
}

Sonrasında ise yukarıda yazdığımız action filterı ilgili API'a ekliyoruz.

[HttpGet]
[CustomFilter]
public IEnumerable<WeatherForecast> Get()
{
    var rng = new Random();
    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();
}

Uygulamayı çalıştırıp sonrasında da dotnet-counters aracıyla monitor etmeye başlıyoruz.

dotnet-counters monitor -p 5944 --counter-list MyCustomSource

Bir sonraki yazıda görüşmek üzere,