Öğretici: .NET Core'da EventCounters kullanarak performansı ölçme
Bu makale şunlar için geçerlidir: ✔️ .NET Core 3.0 SDK ve sonraki sürümler
Bu öğreticide, yüksek sıklıkta olaylarla performansı ölçmek için bir'in nasıl EventCounter kullanılabileceğini öğreneceksiniz. Çeşitli resmi .NET Core paketleri, üçüncü taraf sağlayıcılar tarafından yayımlanan kullanılabilir sayaçları kullanabilir veya izleme için kendi ölçümlerinizi oluşturabilirsiniz.
Bu öğreticide şunları yapacaksınız:
- uygulama EventSource.
- Sayaçları dotnet-counters ile izleyin.
Önkoşullar
Öğreticide aşağıdakiler kullanılır:
- .NET Core 3.1 SDK veya sonraki bir sürüm.
- olay sayaçlarını izlemek için dotnet-counters.
- Tanılanacak örnek hata ayıklama hedef uygulaması.
Kaynağı alma
Örnek uygulama, izleme için temel olarak kullanılır. Örnek ASP.NET Core deposuna örnek tarayıcıdan ulaşabilirsiniz. Zip dosyasını indirir, indirdikten sonra ayıklar ve sık kullandığınız IDE'de açarsınız. Düzgün çalıştığından emin olmak için uygulamayı derleyin ve çalıştırın, ardından uygulamayı durdurun.
EventSource uygulama
Birkaç milisaniyede bir gerçekleşen olaylar için olay başına ek yükün düşük olmasını (milisaniyeden az) istersiniz. Aksi takdirde, performans üzerindeki etkisi önemli olacaktır. Bir olayı günlüğe kaydetmek, diske bir şey yazacağınız anlamına gelir. Disk yeterince hızlı değilse, olayları kaybedersiniz. Olayın günlüğe kaydedilmesi dışında bir çözüme ihtiyacınız vardır.
Çok sayıda olayla ilgilenirken, olay başına ölçüyü bilmek de yararlı değildir. Çoğu zaman tek ihtiyacınız olan bazı istatistikler. Böylece sürecin içindeki istatistikleri alabilir ve arada bir istatistikleri raporlamak için bir olay yazabilirsiniz. EventCounter Bunu yapmanız gerekir.
Aşağıda bir uygulama örneği verilmiştir System.Diagnostics.Tracing.EventSource. MinimalEventCounterSource.cs adlı yeni bir dosya oluşturun ve kaynak olarak kod parçacığını kullanın:
using System.Diagnostics.Tracing;
[EventSource(Name = "Sample.EventCounter.Minimal")]
public sealed class MinimalEventCounterSource : EventSource
{
public static readonly MinimalEventCounterSource Log = new MinimalEventCounterSource();
private EventCounter _requestCounter;
private MinimalEventCounterSource() =>
_requestCounter = new EventCounter("request-time", this)
{
DisplayName = "Request Processing Time",
DisplayUnits = "ms"
};
public void Request(string url, long elapsedMilliseconds)
{
WriteEvent(1, url, elapsedMilliseconds);
_requestCounter?.WriteMetric(elapsedMilliseconds);
}
protected override void Dispose(bool disposing)
{
_requestCounter?.Dispose();
_requestCounter = null;
base.Dispose(disposing);
}
}
satırı EventSource.WriteEvent bölümüdür ve öğesinin EventSourceEventCounterparçası değildir, olay sayacıyla birlikte bir iletiyi günlüğe kaydedebileceğinizi göstermek için yazılmıştır.
Eylem filtresi ekleme
Örnek kaynak kodu bir ASP.NET Core projesidir. Genel olarak toplam istek süresini günlüğe kaydedecek bir eylem filtresi ekleyebilirsiniz. LogRequestTimeFilterAttribute.cs adlı yeni bir dosya oluşturun ve aşağıdaki kodu kullanın:
using System.Diagnostics;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc.Filters;
namespace DiagnosticScenarios
{
public class LogRequestTimeFilterAttribute : ActionFilterAttribute
{
readonly Stopwatch _stopwatch = new Stopwatch();
public override void OnActionExecuting(ActionExecutingContext context) => _stopwatch.Start();
public override void OnActionExecuted(ActionExecutedContext context)
{
_stopwatch.Stop();
MinimalEventCounterSource.Log.Request(
context.HttpContext.Request.GetDisplayUrl(), _stopwatch.ElapsedMilliseconds);
}
}
}
Eylem filtresi, istek başladıktan sonra bir Stopwatch başlatır ve tamamlandıktan sonra durur ve geçen süreyi yakalar. Toplam milisaniye tekil örneğe kaydedilir MinimalEventCounterSource
. Bu filtrenin uygulanması için filtre koleksiyonuna eklemeniz gerekir. Startup.cs dosyasında bu filtreyi ConfigureServices
dahil et içindeki yöntemini güncelleştirin.
public void ConfigureServices(IServiceCollection services) =>
services.AddControllers(options => options.Filters.Add<LogRequestTimeFilterAttribute>())
.AddNewtonsoftJson();
Olay sayacını izleme
uygulaması EventSource ve özel eylem filtresi ile uygulamayı derleyin ve başlatın. Ölçümü öğesine günlüğe EventCounterkaydetmişsinizdir, ancak istatistiklere erişmediğiniz sürece yararlı olmaz. İstatistikleri almak için, olayları istediğiniz sıklıkta tetikleyen bir zamanlayıcı ve olayları yakalamak için bir dinleyici oluşturarak öğesini etkinleştirmeniz EventCounter gerekir. Bunu yapmak için dotnet-counters kullanabilirsiniz.
İzlenebilen .NET işlemlerinin listesini görüntülemek için dotnet-counters ps komutunu kullanın.
dotnet-counters ps
Komutun çıkışındaki işlem tanımlayıcısını dotnet-counters ps
kullanarak, aşağıdaki dotnet-counters monitor
komutla olay sayacını izlemeye başlayabilirsiniz:
dotnet-counters monitor --process-id 2196 --counters Sample.EventCounter.Minimal,Microsoft.AspNetCore.Hosting[total-requests,requests-per-second],System.Runtime[cpu-usage]
dotnet-counters monitor
Komut çalışırken, uç noktaya sürekli istekler göndermeye başlamak için tarayıcıda F5'ihttps://localhost:5001/api/values
tutun. Birkaç saniye sonra q tuşuna basarak durdurun
Press p to pause, r to resume, q to quit.
Status: Running
[Microsoft.AspNetCore.Hosting]
Request Rate / 1 sec 9
Total Requests 134
[System.Runtime]
CPU Usage (%) 13
[Sample.EventCounter.Minimal]
Request Processing Time (ms) 34.5
Komutu dotnet-counters monitor
etkin izleme için harikadır. Ancak, bu tanılama ölçümlerini işleme ve analiz sonrası için toplamak isteyebilirsiniz. Bunun için komutunu kullanın dotnet-counters collect
. collect
switch komutu komutuna monitor
benzer, ancak birkaç ek parametre kabul eder. İstediğiniz çıkış dosyası adını ve biçimini belirtebilirsiniz. diagnostics.json adlı bir JSON dosyası için aşağıdaki komutu kullanın:
dotnet-counters collect --process-id 2196 --format json -o diagnostics.json --counters Sample.EventCounter.Minimal,Microsoft.AspNetCore.Hosting[total-requests,requests-per-second],System.Runtime[cpu-usage]
Komut çalışırken, uç noktaya sürekli istekler göndermeye başlamak için tarayıcıda F5'ihttps://localhost:5001/api/values
basılı tutun. Birkaç saniye sonra q tuşuna basarak durdurun. diagnostics.json dosyası yazılır. Ancak, yazılan JSON dosyası girintili değildir; okunabilirlik için burada girintilenmiştir.
{
"TargetProcess": "DiagnosticScenarios",
"StartTime": "8/5/2020 3:02:45 PM",
"Events": [
{
"timestamp": "2020-08-05 15:02:47Z",
"provider": "System.Runtime",
"name": "CPU Usage (%)",
"counterType": "Metric",
"value": 0
},
{
"timestamp": "2020-08-05 15:02:47Z",
"provider": "Microsoft.AspNetCore.Hosting",
"name": "Request Rate / 1 sec",
"counterType": "Rate",
"value": 0
},
{
"timestamp": "2020-08-05 15:02:47Z",
"provider": "Microsoft.AspNetCore.Hosting",
"name": "Total Requests",
"counterType": "Metric",
"value": 134
},
{
"timestamp": "2020-08-05 15:02:47Z",
"provider": "Sample.EventCounter.Minimal",
"name": "Request Processing Time (ms)",
"counterType": "Metric",
"value": 0
},
{
"timestamp": "2020-08-05 15:02:47Z",
"provider": "System.Runtime",
"name": "CPU Usage (%)",
"counterType": "Metric",
"value": 0
},
{
"timestamp": "2020-08-05 15:02:48Z",
"provider": "Microsoft.AspNetCore.Hosting",
"name": "Request Rate / 1 sec",
"counterType": "Rate",
"value": 0
},
{
"timestamp": "2020-08-05 15:02:48Z",
"provider": "Microsoft.AspNetCore.Hosting",
"name": "Total Requests",
"counterType": "Metric",
"value": 134
},
{
"timestamp": "2020-08-05 15:02:48Z",
"provider": "Sample.EventCounter.Minimal",
"name": "Request Processing Time (ms)",
"counterType": "Metric",
"value": 0
},
{
"timestamp": "2020-08-05 15:02:48Z",
"provider": "System.Runtime",
"name": "CPU Usage (%)",
"counterType": "Metric",
"value": 0
},
{
"timestamp": "2020-08-05 15:02:50Z",
"provider": "Microsoft.AspNetCore.Hosting",
"name": "Request Rate / 1 sec",
"counterType": "Rate",
"value": 0
},
{
"timestamp": "2020-08-05 15:02:50Z",
"provider": "Microsoft.AspNetCore.Hosting",
"name": "Total Requests",
"counterType": "Metric",
"value": 134
},
{
"timestamp": "2020-08-05 15:02:50Z",
"provider": "Sample.EventCounter.Minimal",
"name": "Request Processing Time (ms)",
"counterType": "Metric",
"value": 0
}
]
}