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
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
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:
Open
Extensions.cs
in hetServiceDefaults
project en schuif naar de methodeConfigureOpenTelemetry
. Let op deAddHttpClientInstrumentation()
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(); })
Voer het
AppHost
project uit. Hiermee wordt het Aspire Dashboard gestart.Ga naar de pagina Weer van de
webfrontend
-app om eenHttpClient
aanvraag te genereren voorapiservice
. Vernieuw de pagina meerdere keren om meerdere aanvragen te verzenden.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 vanSystem.Net
te bladeren.
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:
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
Raadpleeg de ServiceDefaults project vanuit uw ASP.NET toepassing. Selecteer in Visual Studio >projectreferentie toevoegen en selecteer het ServiceDefaults project'
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.
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 HttpRequestMessage
een 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 IHttpClientFactory
werkt, kunt u AddHttpMessageHandler gebruiken om de EnrichmentHandler
te 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 MeterListener
of 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, IHttpClientFactory
en 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.ResponseContentRead
gebruikt, 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.