Sdílet prostřednictvím


Kurz: Měření výkonu pomocí eventcounters v .NET Core

Tento článek se týká sady ✔️ .NET Core 3.0 SDK a novějších verzí.

V tomto kurzu se dozvíte, jak EventCounter se dá použít k měření výkonu s vysokou frekvencí událostí. Můžete použít dostupné čítače publikované různými oficiálními balíčky .NET Core nebo externími poskytovateli nebo vytvořit vlastní metriky pro monitorování.

V tomto kurzu:

Požadavky

Kurz používá:

Získání zdroje

Ukázková aplikace se použije jako základ pro monitorování. Ukázkové úložiště ASP.NET Core je k dispozici v prohlížeči ukázek. Stáhnete soubor zip, po stažení ho extrahujete a otevřete ho ve svém oblíbeném integrovaném vývojovém prostředí( IDE). Sestavte a spusťte aplikaci, abyste se ujistili, že funguje správně, a pak aplikaci zastavte.

Implementace eventSource

U událostí, ke kterým dochází každých několik milisekund, budete chtít, aby režie na událost byla nízká (menší než milisekunda). Jinak bude dopad na výkon významný. Protokolování události znamená, že na disk něco napíšete. Pokud disk není dostatečně rychlý, dojde ke ztrátě událostí. Potřebujete jiné řešení než protokolování samotné události.

Při zpracování velkého počtu událostí není ani znalost míry na událost užitečná. Většinou stačí jen nějaké statistiky. Takže můžete získat statistiky v rámci samotného procesu a pak jednou za čas napsat událost, abyste statistiku ohlásili, to je to, co EventCounter se stane.

Níže je příklad implementace System.Diagnostics.Tracing.EventSource. Vytvořte nový soubor s názvem MinimalEventCounterSource.cs a jako zdroj použijte fragment kódu:

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);
    }
}

Řádek EventSource.WriteEvent je EventSource část a není součástí EventCounter, byl napsán tak, aby ukázal, že můžete protokolovat zprávu spolu s čítačem událostí.

Přidání filtru akce

Ukázkový zdrojový kód je projekt ASP.NET Core. Můžete přidat filtr akcí globálně, který zaznamená celkový čas požadavku. Vytvořte nový soubor s názvem LogRequestTimeFilterAttribute.cs a použijte následující kód:

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);
        }
    }
}

Filtr akce spustí Stopwatch při zahájení požadavku a po jeho dokončení se zastaví a zachytí uplynulý čas. Celkový počet milisekund se protokoluje do MinimalEventCounterSource instance singleton. Aby se tento filtr použil, musíte ho přidat do kolekce filtrů. V souboru Startup.cs aktualizujte metodu ConfigureServices v zahrnutí tohoto filtru.

public void ConfigureServices(IServiceCollection services) =>
    services.AddControllers(options => options.Filters.Add<LogRequestTimeFilterAttribute>())
            .AddNewtonsoftJson();

Monitorování čítače událostí

S implementací v objektu EventSource a filtrem vlastní akce sestavte a spusťte aplikaci. Metriku jste zaprotokolovali do EventCounter, ale pokud z ní ke statistikě nepřistupujete, není to užitečné. Abyste získali statistiku, musíte povolit EventCounter funkci tak, že vytvoříte časovač, který se aktivuje tak často, jak chcete, a také naslouchací proces, který bude události zaznamenávat. K tomu můžete použít dotnet-counters.

Pomocí příkazu dotnet-counters ps zobrazte seznam procesů .NET, které lze monitorovat.

dotnet-counters ps

Pomocí identifikátoru procesu z výstupu dotnet-counters ps příkazu můžete spustit monitorování čítače událostí pomocí následujícího dotnet-counters monitor příkazu:

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 Když je příkaz spuštěný, podržte klávesu F5 v prohlížeči, aby se spustily průběžné požadavky na https://localhost:5001/api/values koncový bod. Po několika sekundách přestaňte stisknutím klávesy q

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

Příkaz dotnet-counters monitor je skvělý pro aktivní monitorování. Tyto diagnostické metriky ale můžete chtít shromáždit pro následné zpracování a analýzu. K tomu použijte dotnet-counters collect příkaz . Příkaz collect switch se podobá monitor příkazu , ale přijímá několik dalších parametrů. Můžete zadat název a formát požadovaného výstupního souboru. Pro soubor JSON s názvem diagnostics.json použijte následující příkaz:

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]

Opět platí, že zatímco je příkaz spuštěný, podržte klávesu F5 v prohlížeči, aby se spustily průběžné požadavky na https://localhost:5001/api/values koncový bod. Po několika sekundách zastavte stisknutím klávesy q. Soubor diagnostics.json je zapsaný. Zapsaný soubor JSON však není odsazený. pro čitelnost je odsazený tady.

{
  "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
    }
  ]
}

Další kroky