Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Métricas são medidas numéricas registradas ao longo do tempo. Normalmente, eles são usados para monitorar a integridade de um aplicativo e gerar alertas.
A partir do .NET 8, os componentes System.Net.Http e System.Net.NameResolution são instrumentados para publicar métricas usando a nova API System.Diagnostics.Metrics do .NET .
Essas métricas foram projetadas em cooperação com OpenTelemetry para garantir que sejam consistentes com o padrão e funcionem bem com ferramentas populares como Prometheus e Grafana.
Eles também são multidimensional, o que significa que as medidas estão associadas a pares chave-valor chamados marcas (também conhecidos como atributos ou rótulos). As tags permitem a categorização da medição para ajudar na análise.
Dica
Para obter uma lista abrangente de todos os instrumentos integrados, juntamente com seus atributos, consulte System.Net metrics.
Coletar métricas de System.Net
Para aproveitar a instrumentação de métricas internas, um aplicativo .NET precisa ser configurado para coletar essas métricas. Isso normalmente significa transformá-los para armazenamento e análise externos, por exemplo, em sistemas de monitoramento.
Há várias maneiras de coletar métricas de rede no .NET.
- Para obter uma visão geral rápida utilizando um exemplo simples e autossuficiente, consulte Coletar métricas com dotnet-counters.
- Para a coleta e monitoramento de métricas do tempo de produção, é possível utilizar o Grafana com OpenTelemetry e Prometheus ou o Azure Monitor Application Insights. No entanto, essas ferramentas podem ser inconvenientes para serem usadas em tempo de desenvolvimento devido à sua complexidade.
- Para a coleta de métricas e a solução de problemas durante o tempo de desenvolvimento, recomendamos usar o Aspire, que fornece uma maneira simples, mas extensível, de iniciar métricas e rastreamento distribuído em seu aplicativo e diagnosticar problemas localmente.
- Também é possível reutilizar o projeto Aspire Service Defaults sem a orquestração Aspire, o que é uma maneira prática de introduzir as APIs de configuração de rastreamento e métricas do OpenTelemetry no seu projeto de ASP.NET.
Coletar métricas com dotnet-counters
dotnet-counters é uma ferramenta de linha de comando multiplataforma para exame ad hoc de métricas do .NET e investigação de desempenho de primeiro nível.
Para os fins deste tutorial, crie um aplicativo que envia solicitações HTTP para vários endereços em paralelo.
dotnet new console -o HelloBuiltinMetrics
cd ..\HelloBuiltinMetrics
Substitua o conteúdo de Program.cs pelo seguinte código de exemplo:
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."); }
});
}
Verifique se dotnet-counters está instalado:
dotnet tool install --global dotnet-counters
Inicie o aplicativo HelloBuiltinMetrics.
dotnet run -c Release
Inicie dotnet-counters em uma janela da CLI separada e especifique o nome do processo e os medidores a serem observados e pressione uma tecla no aplicativo HelloBuiltinMetrics para que ele comece a enviar solicitações. Assim que as medidas começarem a chegar, dotnet-counters atualizará continuamente o console com os números mais recentes.
dotnet-counters monitor --counters System.Net.Http,System.Net.NameResolution -n HelloBuiltinMetrics
Coletar métricas com o Aspire
Uma maneira simples de coletar rastreamentos e métricas em aplicativos ASP.NET é usar o Aspire. O Aspire é um conjunto de extensões para .NET para facilitar a criação e o trabalho com aplicativos distribuídos. Um dos benefícios de usar o Aspire é que a telemetria é interna, usando as bibliotecas OpenTelemetry para .NET.
Os modelos de projeto padrão do Aspire contêm um projeto ServiceDefaults. Cada serviço na solução Aspire tem uma referência ao projeto Padrões de Serviço. Os serviços o utilizam para definir e configurar o OTel.
O modelo de projeto de padrões de serviço inclui os pacotes de instrumentação OTel SDK, ASP.NET, HttpClient e Runtime. Esses componentes de instrumentação são configurados no arquivo Extensions.cs. Para dar suporte à visualização de telemetria no Painel do Aspire, o projeto Padrões de Serviço também inclui o exportador OTLP por padrão.
O Aspire Dashboard foi projetado para integrar a observação de telemetria ao ciclo de depuração local, permitindo que os desenvolvedores assegurem que os aplicativos estejam gerando telemetria. A visualização de telemetria também ajuda a diagnosticar esses aplicativos localmente. Ser capaz de observar as chamadas entre serviços é tão útil no momento do debug quanto na produção. O painel do Aspire é iniciado automaticamente quando você F5 o AppHost projeto do Visual Studio ou dotnet run o AppHost projeto da linha de comando.
Passo a passo rápido
Crie um aplicativo de início do Aspire 9 usando
dotnet new:dotnet new aspire-starter-9 --output AspireDemoOu, no Visual Studio, crie um novo projeto e selecione o modelo de aplicativo do Aspire 9 Starter :
Abra
Extensions.csno projetoServiceDefaultse role até o métodoConfigureOpenTelemetry. Observe a chamadaAddHttpClientInstrumentation()inscrevendo-se nos medidores de sistemas de rede..WithMetrics(metrics => { metrics.AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddRuntimeInstrumentation(); })Observe que, no .NET 8+,
AddHttpClientInstrumentation()pode ser substituído por assinaturas de medidores manuais..WithMetrics(metrics => { metrics.AddAspNetCoreInstrumentation() .AddMeter("System.Net.Http") .AddMeter("System.Net.NameResolution") .AddRuntimeInstrumentation(); })Execute o projeto
AppHost. Isso deve iniciar o painel do Aspire.Navegue até a página de previsão do tempo do aplicativo
webfrontend, para gerar uma solicitaçãoHttpClientdestinada aapiservice. Atualize a página diversas vezes para enviar várias solicitações.Retorne ao Painel, navegue até a página de Métricas e selecione o recurso
webfrontend. Ao rolar para baixo, deve ser possível procurar as métricas internas deSystem.Net.
Para obter mais informações sobre o Aspire, consulte:
Reuso do projeto de configurações padrão de serviço sem a orquestração do Aspire
O projeto Padrões do Serviço Aspire fornece uma maneira fácil de configurar o OTel para projetos ASP.NET, mesmo que não esteja utilizando outras partes do Aspire, como o AppHost para orquestração. O projeto Padrões de Serviço está disponível como um modelo de projeto via Visual Studio ou dotnet new. Ele configura o OTel e define o exportador OTLP. Em seguida, você pode usar as variáveis de ambiente OTel para configurar o ponto de extremidade OTLP para o qual enviar telemetria e fornecer as propriedades de recurso para o aplicativo.
As etapas para usar ServiceDefaults fora do Aspire são:
Adicione o projeto ServiceDefaults à solução usando Adicionar Novo Projeto no Visual Studio ou use
dotnet new:dotnet new aspire-servicedefaults --output ServiceDefaultsFaça referência ao projeto ServiceDefaults do seu aplicativo ASP.NET. No Visual Studio, selecione Adicionar>Referência de Projeto e selecione o projeto ServiceDefaults."
Chame a função de configuração do OpenTelemetry
ConfigureOpenTelemetry()como parte da inicialização do configurador de aplicativos.var builder = WebApplication.CreateBuilder(args) builder.ConfigureOpenTelemetry(); // Extension method from ServiceDefaults. var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();
Para obter um passo a passo completo, consulte Exemplo: Usar o OpenTelemetry com OTLP e o painel autônomo do Aspire.
Exibir métricas no Grafana com OpenTelemetry e Prometheus
Para ver como conectar um aplicativo de exemplo com Prometheus e Grafana, siga o passo a passo em Usando o OpenTelemetry com Prometheus, Grafana e Jaeger.
Para enfatizar o HttpClient enviando solicitações paralelas para vários pontos de extremidade, amplie o aplicativo de exemplo com o seguinte ponto de extremidade:
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.";
});
Crie um painel do Grafana selecionando o ícone + na barra de ferramentas superior e selecionando Painel. No editor do painel exibido, insira Conexões Abrir Conexões HTTP/1.1 na caixa Título e a seguinte consulta no campo de expressão PromQL:
sum by(http_connection_state) (http_client_open_connections{network_protocol_version="1.1"})
Selecione Aplicar para salvar e exibir o novo painel. Ele exibe o número de conexões HTTP/1.1 ativas versus ociosas no pool.
Enriquecimento
Enriquecimento é a adição de marcas personalizadas (também conhecidas como atributos ou rótulos) a uma métrica. Isso será útil se um aplicativo quiser adicionar uma categorização personalizada a dashboards ou alertas criados com métricas.
O instrumento http.client.request.duration dá suporte ao enriquecimento registrando retornos de chamada com o HttpMetricsEnrichmentContext.
Observe que esta é uma API de baixo nível e um registro de callback separado é necessário para cada HttpRequestMessage.
Uma forma simples de fazer o registro de retorno de chamada em um único local é implementar um DelegatingHandler personalizado. Isso permite que você intercepte e modifique as solicitações antes que elas sejam encaminhadas para o manipulador interno e enviadas ao servidor:
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);
}
}
Se você estiver trabalhando com IHttpClientFactory, poderá usar AddHttpMessageHandler para registrar o 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");
Nota
Por motivos de desempenho, o retorno de chamada do enriquecimento só é invocado quando o instrumento http.client.request.duration está habilitado, o que significa que algo deve estar coletando as métricas.
Isso pode ser o dotnet-monitor, o exportador do Prometheus, um MeterListener ou um MetricCollector<T>.
Integração de IMeterFactory e IHttpClientFactory
As métricas HTTP foram projetadas com isolamento e capacidade de teste em mente. Esses aspectos são respaldados pelo uso de IMeterFactory, que permite a publicação de métricas por uma instância personalizada de Meter, a fim de manter os medidores isolados uns dos outros.
Por padrão, um Meter global é utilizado para emitir todas as métricas. Esse Meter interno para a biblioteca de System.Net.Http. Esse comportamento pode ser substituído atribuindo uma instância de IMeterFactory personalizada a SocketsHttpHandler.MeterFactory ou HttpClientHandler.MeterFactory.
Nota
O Meter.Name é System.Net.Http para todas as métricas emitidas por HttpClientHandler e SocketsHttpHandler.
Ao trabalhar com Microsoft.Extensions.Http e IHttpClientFactory no .NET 8+, a implementação de IHttpClientFactory padrão escolhe automaticamente a instância de IMeterFactory registrada no IServiceCollection e a atribui ao manipulador primário que cria internamente.
Nota
A partir do .NET 8, o método AddHttpClient chama automaticamente AddMetrics para inicializar os serviços de métricas e registrar a implementação de IMeterFactory padrão com IServiceCollection. O IMeterFactory padrão armazena em cache Meter instâncias por nome, o que significa que existe uma Meter com o nome System.Net.Http por IServiceCollection.
Métricas de teste
O exemplo a seguir demonstra como validar métricas internas em testes de unidade usando xUnit, IHttpClientFactorye MetricCollector<T> do pacote NuGet Microsoft.Extensions.Diagnostics.Testing:
[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étricas versus EventCounters
As métricas têm recursos mais avançados do que EventCounters, principalmente devido à sua natureza multidimensional. Essa multidimensionalidade permite criar consultas sofisticadas em ferramentas como o Prometheus e obter insights sobre um nível que não é possível com EventCounters.
No entanto, a partir do .NET 8, somente os componentes System.Net.Http e System.Net.NameResolutions são instrumentados usando métricas, o que significa que, se você precisar de contadores dos níveis inferiores da pilha, como System.Net.Sockets ou System.Net.Security, deverá usar EventCounters.
Além disso, há algumas diferenças semânticas entre Métricas e seus EventCounters correspondentes.
Por exemplo, ao usar HttpCompletionOption.ResponseContentRead, o current-requests EventCounter considera uma solicitação ativa até o momento em que o último byte do corpo da solicitação foi lido.
Seu equivalente de métricas http.client.active_requests não inclui o tempo gasto lendo o corpo da resposta ao contar as solicitações ativas.
Precisa de mais métricas?
Se você tiver sugestões para outras informações úteis que possam ser expostas por meio de métricas, crie um problema dotnet/runtime.