Delen via


Zelfstudie: Prestaties meten met EventCounters in .NET Core

Dit artikel is van toepassing op: ✔️ .NET Core 3.0 SDK en latere versies

In deze zelfstudie leert u hoe een EventCounter kan worden gebruikt om prestaties te meten met een hoge frequentie van gebeurtenissen. U kunt de beschikbare tellers gebruiken die zijn gepubliceerd door verschillende officiële .NET Core-pakketten of externe providers, of uw eigen metrische gegevens voor bewaking maken.

In deze zelfstudie leert u het volgende:

Vereisten

In de zelfstudie wordt het volgende gebruikt:

De bron ophalen

De voorbeeldtoepassing wordt gebruikt als basis voor bewaking. De voorbeeldopslagplaats ASP.NET Core is beschikbaar in de voorbeeldbrowser. U downloadt het zip-bestand, extraheert het zodra het is gedownload en opent het in uw favoriete IDE. Bouw de toepassing en voer deze uit om ervoor te zorgen dat deze goed werkt. Stop vervolgens de toepassing.

Een gebeurtenisbron implementeren

Voor gebeurtenissen die om de paar milliseconden plaatsvinden, wilt u dat de overhead per gebeurtenis laag is (minder dan een milliseconde). Anders is de impact op de prestaties aanzienlijk. Het vastleggen van een gebeurtenis betekent dat u iets naar de schijf gaat schrijven. Als de schijf niet snel genoeg is, gaan gebeurtenissen verloren. U hebt een andere oplossing nodig dan de gebeurtenis zelf registreren.

Wanneer u te maken krijgt met een groot aantal gebeurtenissen, is het ook niet handig om de meting per gebeurtenis te kennen. Meestal hebt u alleen maar wat statistieken nodig. U kunt dus de statistieken in het proces zelf ophalen en vervolgens af en toe een gebeurtenis schrijven om de statistieken te rapporteren.EventCounter

Hieronder ziet u een voorbeeld van het implementeren van een System.Diagnostics.Tracing.EventSource. Maak een nieuw bestand met de naam MinimalEventCounterSource.cs en gebruik het codefragment als bron:

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

De EventSource.WriteEvent regel is het EventSource deel en maakt geen deel uit van EventCounter. Deze regel is geschreven om te laten zien dat u een bericht samen met de gebeurtenisteller kunt registreren.

Een actiefilter toevoegen

De voorbeeldbroncode is een ASP.NET Core project. U kunt een actiefilter globaal toevoegen waarmee de totale aanvraagtijd wordt bijhouden. Maak een nieuw bestand met de naam LogRequestTimeFilterAttribute.cs en gebruik de volgende code:

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

Het actiefilter start een Stopwatch wanneer de aanvraag begint en stopt nadat deze is voltooid, waarbij de verstreken tijd wordt vastgelegd. Het totale aantal milliseconden wordt vastgelegd in het MinimalEventCounterSource singleton-exemplaar. Als u dit filter wilt toepassen, moet u het toevoegen aan de filterverzameling. Werk in het bestand Startup.cs de ConfigureServices methode bij in dit filter opnemen.

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

Gebeurtenisteller bewaken

Met de implementatie op een EventSource en het aangepaste actiefilter bouwt en start u de toepassing. U hebt de metrische gegevens geregistreerd bij de EventCounter, maar tenzij u de statistieken ervan opent, is het niet nuttig. Als u de statistieken wilt ophalen, moet u de EventCounter inschakelen door een timer te maken die zo vaak als u wilt dat de gebeurtenissen worden geactiveerd, evenals een listener om de gebeurtenissen vast te leggen. Hiervoor kunt u dotnet-tellers gebruiken.

Gebruik de opdracht dotnet-counters ps om een lijst met .NET-processen weer te geven die kunnen worden bewaakt.

dotnet-counters ps

Met behulp van de proces-id uit de uitvoer van de dotnet-counters ps opdracht kunt u beginnen met het bewaken van de gebeurtenisteller met de volgende dotnet-counters monitor opdracht:

dotnet-counters monitor --process-id 2196 --counters Sample.EventCounter.Minimal,Microsoft.AspNetCore.Hosting[total-requests,requests-per-second],System.Runtime[cpu-usage]

Terwijl de dotnet-counters monitor opdracht wordt uitgevoerd, houdt u F5 in de browser ingedrukt om doorlopende aanvragen naar het https://localhost:5001/api/values eindpunt te verzenden. Stop na een paar seconden door op q te drukken

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

De dotnet-counters monitor opdracht is ideaal voor actieve bewaking. Het is echter mogelijk dat u deze diagnostische metrische gegevens wilt verzamelen voor naverwerking en analyse. Gebruik hiervoor de dotnet-counters collect opdracht . De collect opdracht switch is vergelijkbaar met de monitor opdracht, maar accepteert enkele extra parameters. U kunt de gewenste naam en indeling van het uitvoerbestand opgeven. Gebruik voor een JSON-bestand met de naam diagnostics.json de volgende opdracht:

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]

Terwijl de opdracht wordt uitgevoerd, houdt u F5 in de browser ingedrukt om continue aanvragen naar het https://localhost:5001/api/values eindpunt te verzenden. Na een paar seconden stopt u door op q te drukken. Het bestand diagnostics.json is geschreven. Het JSON-bestand dat is geschreven, is echter niet ingesprongen; Voor de leesbaarheid is deze hier ingesprongen.

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

Volgende stappen