Delen via


Metrische netwerkgegevens in .NET

metrische gegevens zijn numerieke metingen die in de loop van de tijd worden gerapporteerd. Ze worden meestal gebruikt om de status van een app te bewaken en waarschuwingen te genereren.

Vanaf .NET 8 worden de System.Net.Http en de System.Net.NameResolution-onderdelen geïnstrueerd om metriek te publiceren met behulp van .NET's nieuwe System.Diagnostics.Metrics-API. Deze metrische gegevens zijn ontworpen in samenwerking met OpenTelemetry- om ervoor te zorgen dat ze consistent zijn met de standaard en goed werken met populaire hulpprogramma's zoals Prometheus en Grafana. Ze zijn ook multidimensionale, wat betekent dat metingen zijn gekoppeld aan sleutel-waardeparen die tags worden genoemd (ook wel kenmerken of labels genoemd). Tags maken de categorisatie van de meting mogelijk om te helpen bij de analyse.

Fooi

Zie System.Net metrische gegevensvoor een uitgebreide lijst met alle ingebouwde instrumenten samen met hun kenmerken.

Metrische gegevens voor System.Net verzamelen

Als u wilt profiteren van de ingebouwde instrumentatie voor metrische gegevens, moet een .NET-app worden geconfigureerd om deze metrische gegevens te verzamelen. Dit betekent doorgaans dat ze worden getransformeerd voor externe opslag en analyse, bijvoorbeeld voor bewakingssystemen.

Er zijn verschillende manieren om metrische netwerkgegevens te verzamelen in .NET.

  • Zie Metrische gegevens verzamelen met dotnet-tellersvoor een kort overzicht met behulp van een eenvoudig, zelfstandig voorbeeld.
  • Voor productietijd verzameling en bewaking van metrische gegevens kunt u Grafana gebruiken met OpenTelemetry en Prometheus of Azure Monitor Application Insights. Deze hulpprogramma's kunnen echter onhandig zijn om tijdens de ontwikkeling te gebruiken vanwege hun complexiteit.
  • Voor ontwikkelingstijd verzameling en probleemoplossing van metrische gegevens raden we u aan .NET Aspire-te gebruiken. Dit biedt een eenvoudige maar uitbreidbare manier om metrische gegevens en gedistribueerde tracering in uw toepassing te starten en problemen lokaal te diagnosticeren.
  • Het is ook mogelijk om de Aspire Service Defaults project te hergebruiken zonder de Aspire-indeling. Dit is een handige manier om de OpenTelemetry-tracerings- en metrische configuratie-API's in uw ASP.NET project te introduceren.

Statistieken verzamelen met dotnet-counters

dotnet-counters is een platformoverschrijdend opdrachtregelprogramma voor ad-hoconderzoek van .NET-metrische gegevens en prestatieonderzoek op het eerste niveau.

Maak voor deze zelfstudie een app waarmee HTTP-aanvragen parallel naar verschillende eindpunten worden verzonden.

dotnet new console -o HelloBuiltinMetrics
cd ..\HelloBuiltinMetrics

Vervang de inhoud van Program.cs door de volgende voorbeeldcode:

using System.Net;

string[] uris = ["http://example.com", "http://httpbin.org/get", "https://example.com", "https://httpbin.org/get"];
using HttpClient client = new()
{
    DefaultRequestVersion = HttpVersion.Version20
};

Console.WriteLine("Press any key to start.");
Console.ReadKey();

while (!Console.KeyAvailable)
{
    await Parallel.ForAsync(0, Random.Shared.Next(20), async (_, ct) =>
    {
        string uri = uris[Random.Shared.Next(uris.Length)];
        try
        {
            byte[] bytes = await client.GetByteArrayAsync(uri, ct);
            await Console.Out.WriteLineAsync($"{uri} - received {bytes.Length} bytes.");
        }
        catch { await Console.Out.WriteLineAsync($"{uri} - failed."); }
    });
}

Zorg ervoor dat dotnet-counters is geïnstalleerd:

dotnet tool install --global dotnet-counters

Start de HelloBuiltinMetrics-app.

dotnet run -c Release

Start dotnet-counters in een afzonderlijk CLI-venster en geef de procesnaam en de meters op die moeten worden bekeken. Druk vervolgens op een toets in de HelloBuiltinMetrics-app, zodat er aanvragen worden verzonden. Zodra de metingen binnenkomen, vernieuwt dotnet-counters de console continu met de nieuwste waarden.

dotnet-counters monitor --counters System.Net.Http,System.Net.NameResolution -n HelloBuiltinMetrics

uitvoer van dotnet-counters

Metrische gegevens verzamelen met .NET Aspire

Een eenvoudige manier om traceringen en metrische gegevens te verzamelen in ASP.NET toepassingen is het gebruik van .NET Aspire. .NET Aspire is een set extensies voor .NET, zodat u eenvoudig gedistribueerde toepassingen kunt maken en ermee kunt werken. Een van de voordelen van het gebruik van .NET Aspire is dat telemetrie is ingebouwd met behulp van de OpenTelemetry-bibliotheken voor .NET.

De standaardprojectsjablonen voor .NET Aspire bevatten een ServiceDefaults project. Elke service in de .NET Aspire-oplossing heeft een verwijzing naar het servicestandaardproject. De services gebruiken deze om OTel in te stellen en te configureren.

De servicestandaardprojectsjabloon bevat de OTel SDK-, ASP.NET-, HttpClient- en Runtime Instrumentation-pakketten. Deze instrumentatieonderdelen worden geconfigureerd in het Extensions.cs-bestand. Ter ondersteuning van telemetrievisualisatie in Aspire Dashboard bevat het project Service Defaults standaard ook de OTLP-exporteur.

Aspire Dashboard is ontworpen om telemetrieobservatie naar de lokale foutopsporingscyclus te brengen, waardoor ontwikkelaars ervoor kunnen zorgen dat de toepassingen telemetrie produceren. De telemetrievisualisatie helpt ook om deze toepassingen lokaal te diagnosticeren. Het observeren van de aanroepen tussen services is net zo nuttig tijdens foutopsporingstijd als in productie. Het .NET Aspire-dashboard wordt automatisch gestart wanneer u F5 het AppHost project vanuit Visual Studio of dotnet run het AppHost project vanaf de commandoregel.

Snel overzicht

  1. Maak een .NET Aspire 9 Starter App met behulp van dotnet new:

    dotnet new aspire-starter-9 --output AspireDemo
    

    Of maak in Visual Studio een nieuw project en selecteer de sjabloon .NET Aspire 9 Starter App:

    Een .NET Aspire 9 Starter-app maken in Visual Studio

  2. Open Extensions.cs in het ServiceDefaults project en schuif naar de methode ConfigureOpenTelemetry. Let op de AddHttpClientInstrumentation() aanroep die zich abonneert op de netwerkmeters.

    .WithMetrics(metrics =>
    {
        metrics.AddAspNetCoreInstrumentation()
            .AddHttpClientInstrumentation()
            .AddRuntimeInstrumentation();
    })
    

    Houd er rekening mee dat op .NET 8+ AddHttpClientInstrumentation() kan worden vervangen door handmatige meterabonnementen:

    .WithMetrics(metrics =>
    {
        metrics.AddAspNetCoreInstrumentation()
            .AddMeter("System.Net.Http")
            .AddMeter("System.Net.NameResolution")
            .AddRuntimeInstrumentation();
    })
    
  3. Voer het AppHost project uit. Hiermee wordt het Aspire Dashboard gestart.

  4. Ga naar de pagina Weer van de webfrontend-app om een HttpClient aanvraag te genereren voor apiservice. Vernieuw de pagina meerdere keren om meerdere aanvragen te verzenden.

  5. Ga terug naar het dashboard, ga naar de pagina Metrische gegevens en selecteer de webfrontend resource. Als u omlaag schuift, moet u in staat zijn om door de ingebouwde metrische gegevens van System.Net te bladeren.

    Metrische netwerkgegevens in Aspire Dashboard

Zie voor meer informatie over .NET Aspire:

Standaardinstellingen van de service opnieuw gebruiken zonder .NET Aspire-orkestratie.

Het project Aspire Service Defaults biedt een eenvoudige manier om OTel te configureren voor ASP.NET projecten, zelfs als de rest van .NET Aspire zoals de AppHost voor orchestration niet wordt gebruikt. Het servicestandaardproject is beschikbaar als een projectsjabloon via Visual Studio of dotnet new. Het configureert OTel en stelt de OTLP-exporteur in. Vervolgens kunt u de omgevingsvariabelen van OTel gebruiken om het OTLP-eindpunt te configureren voor het verzenden van telemetrie naar en de resource-eigenschappen voor de toepassing op te geven.

De stappen voor het gebruik van ServiceDefaults buiten .NET Aspire zijn:

  1. Voeg het ServiceDefaults--project toe aan de oplossing met behulp van Nieuw project toevoegen in Visual Studio of gebruik dotnet new:

    dotnet new aspire-servicedefaults --output ServiceDefaults
    
  2. Raadpleeg de ServiceDefaults project vanuit uw ASP.NET toepassing. Selecteer in Visual Studio >projectreferentie toevoegen en selecteer het ServiceDefaults project'

  3. Roep de OpenTelemetry-instelfunctie ConfigureOpenTelemetry() aan als onderdeel van de initialisatie van je applicatiebouwer.

    var builder = WebApplication.CreateBuilder(args)
    builder.ConfigureOpenTelemetry(); // Extension method from ServiceDefaults.
    var app = builder.Build();
    app.MapGet("/", () => "Hello World!");
    app.Run();
    

Zie Voorbeeld: OpenTelemetry gebruiken met OTLP en het zelfstandige Aspire Dashboardvoor een volledig overzicht.

Metrische gegevens weergeven in Grafana met OpenTelemetry en Prometheus

Als u wilt zien hoe u een voorbeeld-app verbindt met Prometheus en Grafana, volgt u de procedure in OpenTelemetry gebruiken met Prometheus, Grafana en Jaeger.

Als u HttpClient wilt benadrukken door parallelle aanvragen naar verschillende eindpunten te verzenden, kunt u de voorbeeld-app uitbreiden met het volgende eindpunt:

app.MapGet("/ClientStress", async Task<string> (ILogger<Program> logger, HttpClient client) =>
{
    string[] uris = ["http://example.com", "http://httpbin.org/get", "https://example.com", "https://httpbin.org/get"];
    await Parallel.ForAsync(0, 50, async (_, ct) =>
    {
        string uri = uris[Random.Shared.Next(uris.Length)];

        try
        {
            await client.GetAsync(uri, ct);
            logger.LogInformation($"{uri} - done.");
        }
        catch { logger.LogInformation($"{uri} - failed."); }
    });
    return "Sent 50 requests to example.com and httpbin.org.";
});

Maak een Grafana-dashboard door het pictogram + op de bovenste werkbalk te selecteren en vervolgens Dashboardte selecteren. Voer in de dashboardeditor die verschijnt Open HTTP/1.1-verbindingen in het vak Titel in en de volgende query in het veld PromQL-expressie:

sum by(http_connection_state) (http_client_open_connections{network_protocol_version="1.1"})

Selecteer en klik op Toepassen om het nieuwe dashboard op te slaan en weer te geven. Hiermee wordt het aantal actieve en niet-actieve HTTP/1.1-verbindingen in de pool weergegeven.

HTTP/1.1-verbindingen in Grafana

Verrijking

Verrijking is de toevoeging van aangepaste tags (ook wel kenmerken of labels genoemd) aan een metrische waarde. Dit is handig als een app een aangepaste categorisatie wil toevoegen aan dashboards of waarschuwingen die zijn gebouwd met metrische gegevens. Het http.client.request.duration-instrument ondersteunt verrijking door callbacks te registreren bij de HttpMetricsEnrichmentContext. Houd er rekening mee dat dit een API op laag niveau is en dat er voor elke HttpRequestMessageeen afzonderlijke callback-registratie nodig is.

Een eenvoudige manier om de callback-registratie op één plaats uit te voeren, is door een aangepaste DelegatingHandlerte implementeren. Hiermee kunt u de aanvragen onderscheppen en wijzigen voordat ze worden doorgestuurd naar de binnenste handler en naar de server worden verzonden:

using System.Net.Http.Metrics;

using HttpClient client = new(new EnrichmentHandler() { InnerHandler = new HttpClientHandler() });

await client.GetStringAsync("https://httpbin.org/response-headers?Enrichment-Value=A");
await client.GetStringAsync("https://httpbin.org/response-headers?Enrichment-Value=B");

sealed class EnrichmentHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        HttpMetricsEnrichmentContext.AddCallback(request, static context =>
        {
            if (context.Response is not null) // Response is null when an exception occurs.
            {
                // Use any information available on the request or the response to emit custom tags.
                string? value = context.Response.Headers.GetValues("Enrichment-Value").FirstOrDefault();
                if (value != null)
                {
                    context.AddCustomTag("enrichment_value", value);
                }
            }
        });
        return base.SendAsync(request, cancellationToken);
    }
}

Als u met IHttpClientFactorywerkt, kunt u AddHttpMessageHandler gebruiken om de EnrichmentHandlerte registreren:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Net.Http.Metrics;

ServiceCollection services = new();
services.AddHttpClient(Options.DefaultName).AddHttpMessageHandler(() => new EnrichmentHandler());

ServiceProvider serviceProvider = services.BuildServiceProvider();
HttpClient client = serviceProvider.GetRequiredService<HttpClient>();

await client.GetStringAsync("https://httpbin.org/response-headers?Enrichment-Value=A");
await client.GetStringAsync("https://httpbin.org/response-headers?Enrichment-Value=B");

Notitie

Om prestatieredenen wordt de verrijkingscallback alleen aangeroepen wanneer het http.client.request.duration-instrument is ingeschakeld, wat betekent dat er iets moet zijn om de metrieken te verzamelen. Dit kan dotnet-monitor, Prometheus-exporteur, een MeterListenerof een MetricCollector<T>zijn.

integratie van IMeterFactory en IHttpClientFactory

HTTP-metrische gegevens zijn ontworpen met isolatie en testbaarheid in gedachten. Deze aspecten worden ondersteund door het gebruik van IMeterFactory, waardoor metrische gegevens kunnen worden gepubliceerd door een aangepast Meter-exemplaar om Meters geïsoleerd van elkaar te houden. Standaard wordt een globale Meter gebruikt om alle metrische gegevens te verzenden. Dit Meter is intern voor de System.Net.Http-bibliotheek. Dit gedrag kan worden overschreven door een aangepast IMeterFactory exemplaar toe te wijzen aan SocketsHttpHandler.MeterFactory of HttpClientHandler.MeterFactory.

Notitie

De Meter.Name is System.Net.Http voor alle metrische gegevens die worden verzonden door HttpClientHandler en SocketsHttpHandler.

Wanneer u met Microsoft.Extensions.Http en IHttpClientFactory op .NET 8+ werkt, kiest de standaard-IHttpClientFactory-implementatie automatisch het IMeterFactory exemplaar dat is geregistreerd in de IServiceCollection en wijst deze toe aan de primaire handler die intern wordt gemaakt.

Notitie

Vanaf .NET 8 roept de AddHttpClient methode automatisch AddMetrics aan om de metrische services te initialiseren en de standaard-IMeterFactory-implementatie te registreren bij IServiceCollection. De standaard IMeterFactory slaat Meter exemplaren op naam op, wat betekent dat er één Meter is met de naam System.Net.Http per IServiceCollection.

Metrische gegevens testen

In het volgende voorbeeld ziet u hoe u ingebouwde metrische gegevens in eenheidstests kunt valideren met behulp van xUnit, IHttpClientFactoryen MetricCollector<T> uit het Microsoft.Extensions.Diagnostics.Testing NuGet-pakket:

[Fact]
public async Task RequestDurationTest()
{
    // Arrange
    ServiceCollection services = new();
    services.AddHttpClient();
    ServiceProvider serviceProvider = services.BuildServiceProvider();
    var meterFactory = serviceProvider.GetService<IMeterFactory>();
    var collector = new MetricCollector<double>(meterFactory,
        "System.Net.Http", "http.client.request.duration");
    var client = serviceProvider.GetRequiredService<HttpClient>();

    // Act
    await client.GetStringAsync("http://example.com");

    // Assert
    await collector.WaitForMeasurementsAsync(minCount: 1).WaitAsync(TimeSpan.FromSeconds(5));
    Assert.Collection(collector.GetMeasurementSnapshot(),
        measurement =>
        {
            Assert.Equal("http", measurement.Tags["url.scheme"]);
            Assert.Equal("GET", measurement.Tags["http.request.method"]);
        });
}

Metrische gegevens versus EventCounters

Metrische gegevens zijn uitgebreidere dan EventCounters, met name vanwege hun multidimensionale aard. Met deze multidimensionale functionaliteit kunt u geavanceerde query's maken in hulpprogramma's zoals Prometheus en inzichten verkrijgen op een niveau dat niet mogelijk is met EventCounters.

Vanaf .NET 8 worden echter alleen de System.Net.Http en de System.Net.NameResolutions-onderdelen geïnstrueerd met behulp van metrische gegevens, wat betekent dat als u tellers van de lagere niveaus van de stack nodig hebt, zoals System.Net.Sockets of System.Net.Security, u EventCounters moet gebruiken.

Bovendien zijn er enkele semantische verschillen tussen metrische gegevens en hun overeenkomende EventCounters. Wanneer u bijvoorbeeld HttpCompletionOption.ResponseContentReadgebruikt, beschouwt de current-requests EventCounter een aanvraag als actief tot het moment waarop de laatste byte van de aanvraagbody is gelezen. De tegenhanger voor metrische gegevens http.client.active_requests bevat niet de tijd die is besteed aan het lezen van de antwoordtekst bij het tellen van de actieve aanvragen.

Meer metrische gegevens nodig?

Als u suggesties hebt voor andere nuttige informatie die via metrische gegevens kan worden weergegeven, maakt u een dotnet/runtime-issue.