Nätverksmått i .NET
Mått är numeriska mått som rapporteras över tid. De används vanligtvis för att övervaka hälsotillståndet för en app och generera aviseringar.
Från och med .NET 8 instrumenteras System.Net.Http
- och System.Net.NameResolution
-komponenterna för att publicera mått med hjälp av . NET:s nya System.Diagnostics.Metrics API.
Dessa mått utformades i samarbete med OpenTelemetry för att se till att de överensstämmer med standarden och fungerar bra med populära verktyg som Prometheus och Grafana.
De är också flerdimensionella, vilket innebär att mått associeras med nyckel/värde-par som kallas taggar (även kallade attribut eller etiketter). Taggar gör det möjligt att kategorisera måttet för att hjälpa till med analysen.
Tips
En omfattande lista över alla inbyggda instrument tillsammans med deras attribut finns i System.Net mått.
Samla in System.Net metrik
För att kunna dra nytta av den inbyggda måttinstrumentationen måste en .NET-app konfigureras för att samla in dessa mått. Detta innebär vanligtvis att omvandla dem för extern lagring och analys, till exempel till övervakningssystem.
Det finns flera sätt att samla in nätverksmått i .NET.
- En snabb översikt med ett enkelt, fristående exempel finns i Samla in mått med dotnet-counters.
- För insamling och övervakning av för produktionstid kan du använda Grafana med OpenTelemetry och Prometheus eller Azure Monitor Application Insights. Dessa verktyg kan dock vara obekväma att använda vid utvecklingstillfället på grund av deras komplexitet.
- För insamling och felsökning av utvecklingstidsmått för rekommenderar vi att du använder .NET Aspire, vilket ger ett enkelt men utökningsbart sätt att påbörja mätvärden och för distribuerad spårning i din applikation och diagnostisera problem lokalt.
- Det går också att återanvända projektet Aspire Service Defaults utan Aspire-orkestrering, vilket är ett praktiskt sätt att introducera OpenTelemetry-spårnings- och måttkonfigurations-API:erna i ditt ASP.NET projekt.
Samla in metrik med dotnet-counters
dotnet-counters
är ett plattformsoberoende kommandoradsverktyg för ad hoc-undersökning av .NET-mått och prestandaundersökning på första nivån.
För den här självstudien skapar du en app som skickar HTTP-begäranden till olika slutpunkter parallellt.
dotnet new console -o HelloBuiltinMetrics
cd ..\HelloBuiltinMetrics
Ersätt innehållet i Program.cs
med följande exempelkod:
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."); }
});
}
Kontrollera att dotnet-counters
är installerat:
dotnet tool install --global dotnet-counters
Starta appen HelloBuiltinMetrics.
dotnet run -c Release
Starta dotnet-counters
i ett separat CLI-fönster och ange processnamnet och de mätare som ska övervakas och tryck sedan på en tangent i HelloBuiltinMetrics-appen så att den börjar skicka begäranden. När mätningarna börjar landa uppdaterar dotnet-counters
konsolen kontinuerligt med de senaste siffrorna:
dotnet-counters monitor --counters System.Net.Http,System.Net.NameResolution -n HelloBuiltinMetrics
Samla in mått med .NET Aspire
Ett enkelt sätt att samla in spårningar och mått i ASP.NET program är att använda .NET Aspire-. .NET Aspire är en uppsättning tillägg till .NET för att göra det enkelt att skapa och arbeta med distribuerade program. En av fördelarna med att använda .NET Aspire är att telemetri är inbyggd med hjälp av OpenTelemetry-biblioteken för .NET.
Standardprojektmallarna för .NET Aspire innehåller ett ServiceDefaults
projekt. Varje tjänst i .NET Aspire-lösningen har en referens till servicestandardprojektet. Tjänsterna använder den för att konfigurera OTel.
Projektmallen Service Defaults innehåller paketen OTel SDK, ASP.NET, HttpClient och Runtime Instrumentation. Dessa instrumentationskomponenter konfigureras i filen Extensions.cs. För att stödja telemetrivisualisering i Aspire-instrumentpanelen innehåller servicestandardprojektet även OTLP-exportören som standard.
Aspire Dashboard är utformad för att ge telemetriobservation till den lokala felsökningscykeln, vilket gör det möjligt för utvecklare att se till att programmen producerar telemetri. Telemetrivisualiseringen hjälper också till att diagnostisera dessa program lokalt. Att kunna observera anropen mellan tjänster är lika användbart vid felsökning som i produktion. .NET Aspire-instrumentpanelen startas automatiskt när du F5AppHost
Project från Visual Studio eller dotnet run
AppHost
-projektet från kommandoraden.
Snabb genomgång
Skapa en .NET Aspire 9 Starter App med hjälp av
dotnet new
:dotnet new aspire-starter-9 --output AspireDemo
Eller i Visual Studio skapar du ett nytt projekt och väljer mallen .NET Aspire 9 Starter App:
Öppna
Extensions.cs
i projektetServiceDefaults
och rulla till metodenConfigureOpenTelemetry
. Observera detAddHttpClientInstrumentation()
-samtal som används för att prenumerera på data från nätverksmätarna..WithMetrics(metrics => { metrics.AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddRuntimeInstrumentation(); })
Observera att på .NET 8+ kan
AddHttpClientInstrumentation()
ersättas med manuella mätarprenumerationer:.WithMetrics(metrics => { metrics.AddAspNetCoreInstrumentation() .AddMeter("System.Net.Http") .AddMeter("System.Net.NameResolution") .AddRuntimeInstrumentation(); })
Kör projektet
AppHost
. Detta bör öppna Aspire-kontrollpanelen.Gå till vädersidan i appen
webfrontend
för att skicka enHttpClient
-förfrågan tillapiservice
. Uppdatera sidan flera gånger för att skicka flera begäranden.Gå tillbaka till instrumentpanelen, gå till sidan Mått och välj resursen
webfrontend
. Om du rullar nedåt bör du kunna bläddra bland de inbyggda måtten förSystem.Net
.
Mer information om .NET Aspire finns i:
- översikt över Aspire
- telemetri i Aspire
- Aspire Dashboard
Återanvänd servicestandardprojekt utan .NET Aspire-orkestrering
Projektet Aspire Service Defaults är ett enkelt sätt att konfigurera OTel för ASP.NET projekt, även om du inte använder resten av .NET Aspire- som AppHost för orkestrering. Service Defaults-projektet är tillgängligt som en projektmall via Visual Studio eller dotnet new
. Den konfigurerar OTel och ställer in OTLP-exportören. Du kan sedan använda miljövariablerna OTel för att konfigurera OTLP-slutpunkten att skicka telemetri till och ange resursegenskaperna för programmet.
Stegen för att använda ServiceDefaults utanför .NET Aspire är:
Lägg till projektet ServiceDefaults i lösningen med hjälp av Lägg till nytt projekt i Visual Studio eller använd
dotnet new
:dotnet new aspire-servicedefaults --output ServiceDefaults
Referera till projektet ServiceDefaults från ditt ASP.NET-program. I Visual Studio väljer du Lägg till>projektreferens och väljer projektet ServiceDefaults"
Anropa installationsfunktionen OpenTelemetry
ConfigureOpenTelemetry()
som en del av programverktygets initiering.var builder = WebApplication.CreateBuilder(args) builder.ConfigureOpenTelemetry(); // Extension method from ServiceDefaults. var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();
En fullständig genomgång finns i Exempel: Använd OpenTelemetry med OTLP och den fristående Aspire-instrumentpanelen.
Visa mått i Grafana med OpenTelemetry och Prometheus
Om du vill se hur du ansluter en exempelapp med Prometheus och Grafana följer du genomgången i Using OpenTelemetry with Prometheus, Grafana och Jaeger.
För att betona HttpClient
genom att skicka parallella begäranden till olika slutpunkter utökar du exempelappen med följande slutpunkt:
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.";
});
Skapa en Grafana-instrumentpanel genom att välja ikonen + i det översta verktygsfältet och sedan välja Instrumentpanel. I instrumentpanelsredigeraren som visas anger du Öppna HTTP/1.1-anslutningar i rutan Rubrik och följande fråga i fältet PromQL-uttryck:
sum by(http_connection_state) (http_client_open_connections{network_protocol_version="1.1"})
Välj Använd för att spara och visa den nya instrumentpanelen. Det visar antalet aktiva och inaktiva HTTP/1.1-anslutningar i poolen.
Anrikning
Berikning är att lägga till anpassade taggar (även kallade attribut eller etiketter) till ett mätvärde. Detta är användbart om en app vill lägga till en anpassad kategorisering till instrumentpaneler eller aviseringar som byggs på metrik.
http.client.request.duration
-instrumentet stöder berikning genom att registrera återanrop med HttpMetricsEnrichmentContext.
Observera att detta är ett API på låg nivå och att det krävs en separat återanropsregistrering för varje HttpRequestMessage
.
Ett enkelt sätt att göra återanropsregistreringen på en enda plats är att implementera en anpassad DelegatingHandler. På så sätt kan du fånga upp och ändra begäranden innan de vidarebefordras till den inre hanteraren och skickas till servern:
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);
}
}
Om du arbetar med IHttpClientFactory
kan du använda AddHttpMessageHandler för att registrera EnrichmentHandler
:
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");
Anteckning
Av prestandaskäl anropas återanropet för berikning endast när http.client.request.duration
instrument är aktiverat, vilket innebär att något bör samla in måtten.
Detta kan vara dotnet-monitor
, Prometheus-exportör, en MeterListener
, eller en MetricCollector<T>
.
IMeterFactory
och IHttpClientFactory
integrering
HTTP-mått utformades med isolering och testbarhet i åtanke. Dessa aspekter stöds av användningen av IMeterFactory, som möjliggör publicering av mått från en anpassad Meter-instans för att hålla Meters isolerade från varandra.
Som standard används en global Meter för att sända ut alla mått. Detta är Meter internt i System.Net.Http
-biblioteket. Det här beteendet kan åsidosättas genom att tilldela en anpassad IMeterFactory-instans till SocketsHttpHandler.MeterFactory eller HttpClientHandler.MeterFactory.
Anmärkning
Meter.Name är System.Net.Http
för alla mått som genereras av HttpClientHandler
och SocketsHttpHandler
.
När du arbetar med Microsoft.Extensions.Http
och IHttpClientFactory
på .NET 8+ väljer standardimplementeringen IHttpClientFactory
automatiskt den IMeterFactory
instans som registrerats i IServiceCollection och tilldelar den till den primära hanteraren som skapas internt.
Not
Från och med .NET 8 anropar AddHttpClient-metoden automatiskt AddMetrics för att initiera måtttjänsterna och registrera standardimplementeringen IMeterFactory med IServiceCollection. Standard-IMeterFactory cachelagrar Meter instanser efter namn, vilket innebär att det finns en Meter med namnet System.Net.Http
per IServiceCollection.
Testmått
I följande exempel visas hur du validerar inbyggda mått i enhetstester med xUnit, IHttpClientFactory
och MetricCollector<T>
från Microsoft.Extensions.Diagnostics.Testing
NuGet-paketet:
[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"]);
});
}
Mått jämfört med EventCounters
Metriker är mer funktionsrika än EventCounters, framför allt på grund av deras flerdimensionella natur. Med den här flerdimensionelliteten kan du skapa avancerade frågor i verktyg som Prometheus och få insikter på en nivå som inte är möjlig med EventCounters.
Från och med .NET 8 instrumenteras dock endast System.Net.Http
- och System.Net.NameResolutions
-komponenterna med hjälp av mått, vilket innebär att om du behöver räknare från de lägre nivåerna i stacken, till exempel System.Net.Sockets
eller System.Net.Security
, måste du använda EventCounters.
Dessutom finns det vissa semantiska skillnader mellan Mått och deras matchande EventCounters.
När du till exempel använder HttpCompletionOption.ResponseContentRead
anser current-requests
EventCounter att en begäran är aktiv fram till det ögonblick då den sista byte av begärandetexten har lästs.
Dess måttmotsvarighet http.client.active_requests
inkluderar inte den tid som ägnas åt att läsa svarstexten när de aktiva begärandena räknas.
Behöver du fler mått?
Om du har förslag på annan användbar information som kan exponeras via mått, skapa ett dotnet/runtime-ärende.