ASP.NET Core métricas

As métricas são medições numéricas relatadas ao longo do tempo. Use-os para monitorizar o estado de saúde de uma aplicação e gerar alertas. Por exemplo, um serviço Web pode controlar quantos:

  • Pedidos que recebe por segundo.
  • Milissegundos que demora a responder.
  • Respostas que envia com erro.

Reporte estas métricas a um sistema de monitorização a intervalos regulares. Configure painéis para visualizar métricas e criar alertas para notificar as pessoas sobre problemas. Se o serviço Web se destinar a responder a solicitações dentro de 400 ms e começar a responder em 600 ms, o sistema de monitoramento poderá notificar a equipe de operações de que a resposta do aplicativo está mais lenta do que o normal.

A lista abrangente de todos os instrumentos, juntamente com os seus atributos, está descrita nas métricas incorporadas do ASP.NET Core.

Utilizar métricas

O uso de métricas envolve o seguinte:

  • Instrumentação: o código nas bibliotecas .NET realiza medições e associa essas medições a um nome de métrica. O .NET e o ASP.NET Core incluem muitas métricas internas.
  • Recolha e armazenamento: Um aplicativo .NET configura métricas nomeadas a serem transmitidas do aplicativo para armazenamento externo e análise. Algumas ferramentas podem realizar a configuração fora da aplicação usando ficheiros de configuração ou uma ferramenta de interface.
  • Visualização: Uma ferramenta que pode exibir as métricas em um formato legível por humanos. Por exemplo, Grafana e Prometheus.
  • Alerta: Uma ferramenta que fornece notificações quando uma métrica excede um limite. Por exemplo, se o tempo médio de resposta de um serviço Web exceder 400 ms, um alerta poderá ser enviado à equipe de operações.
  • Análise: Uma ferramenta que pode analisar as métricas ao longo do tempo. Esta ferramenta é frequentemente um painel web que pode ser personalizado para mostrar as métricas mais importantes para uma aplicação específica.

O código instrumentado pode registar medições numéricas, mas para criar métricas úteis para monitorização, é necessário agregar, transmitir e armazenar as medições. O processo de agregação, transmissão e armazenamento de dados é chamado de coleta. Este tutorial mostra vários exemplos de coleta e exibição de métricas:

Também pode associar medições a pares-chave-valor chamados etiquetas, que permitem categorizar dados para análise. Para obter mais informações, consulte Métricas multidimensionais.

Criar o aplicativo inicial

Crie um novo aplicativo ASP.NET Core com o seguinte comando:

dotnet new web -o WebMetric
cd WebMetric
dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore --prerelease
dotnet add package OpenTelemetry.Extensions.Hosting

Substitua o conteúdo de Program.cs pelo seguinte código:

using OpenTelemetry.Metrics;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
    .WithMetrics(builder =>
    {
        builder.AddPrometheusExporter();

        builder.AddMeter("Microsoft.AspNetCore.Hosting",
                         "Microsoft.AspNetCore.Server.Kestrel");
        builder.AddView("http.server.request.duration",
            new ExplicitBucketHistogramConfiguration
            {
                Boundaries = new double[] { 0, 0.005, 0.01, 0.025, 0.05,
                       0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 }
            });
    });
var app = builder.Build();

app.MapPrometheusScrapingEndpoint();

app.MapGet("/", () => "Hello OpenTelemetry! ticks:"
                     + DateTime.Now.Ticks.ToString()[^3..]);

app.Run();

Veja métricas com o dotnet-counters

dotnet-counters é uma ferramenta de linha de comando que pode exibir métricas ao vivo para aplicativos .NET sob demanda. Ele não requer configuração, tornando-o útil para investigações ad hoc ou verificação de que a instrumentação métrica está funcionando. Funciona tanto com APIs baseadas em System.Diagnostics.Metrics quanto com Contadores de Eventos.

Se a ferramenta dotnet-counters não estiver instalada, execute o seguinte comando:

dotnet tool update -g dotnet-counters

Enquanto o aplicativo de teste estiver em execução, inicie dotnet-counters. O comando a seguir mostra um exemplo de dotnet-counters monitorando todas as métricas do medidor de Microsoft.AspNetCore.Hosting.

dotnet-counters monitor -n WebMetric --counters Microsoft.AspNetCore.Hosting

É exibida uma saída semelhante à seguinte:

Press p to pause, r to resume, q to quit.
    Status: Running

[Microsoft.AspNetCore.Hosting]
    http-server-current-requests
        host=localhost,method=GET,port=5045,scheme=http                    0
    http-server-request-duration (s)
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0.001
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0.001
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0.001
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0

Para obter mais informações, consulte dotnet-counters.

Enriquecer a métrica de pedidos do ASP.NET Core

ASP.NET Core tem muitas métricas integradas. A métrica http.server.request.duration:

  • Registra a duração das solicitações HTTP no servidor.
  • Captura informações de solicitação em tags, como a rota correspondente e o código de status da resposta.

A http.server.request.duration métrica suporta o enriquecimento de etiquetas usando IHttpMetricsTagsFeature. Enriquecimento é quando uma biblioteca ou aplicativo adiciona suas próprias tags a uma métrica. Esta funcionalidade é útil se uma aplicação quiser adicionar uma categorização personalizada aos dashboards ou alertas construídos com métricas.

using Microsoft.AspNetCore.Http.Features;

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

app.Use(async (context, next) =>
{
    var tagsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
    if (tagsFeature != null)
    {
        var source = context.Request.Query["utm_medium"].ToString() switch
        {
            "" => "none",
            "social" => "social",
            "email" => "email",
            "organic" => "organic",
            _ => "other"
        };
        tagsFeature.Tags.Add(new KeyValuePair<string, object?>("mkt_medium", source));
    }

    await next.Invoke();
});

app.MapGet("/", () => "Hello World!");

app.Run();

O exemplo anterior:

  • Adiciona middleware para enriquecer a métrica de solicitação ASP.NET Core.
  • Obtém o IHttpMetricsTagsFeature do HttpContext. A funcionalidade está presente no contexto apenas se alguém estiver a ouvir a métrica. Verifique se IHttpMetricsTagsFeature não está null antes de o utilizar.
  • Adiciona uma tag personalizada contendo a fonte de marketing da solicitação à métrica http.server.request.duration.
    • A tag tem o nome mkt_medium e um valor baseado no valor da cadeia de caracteres de consulta utm_medium. O valor utm_medium é resolvido para um intervalo conhecido de valores.
    • A tag permite que as solicitações sejam categorizadas por tipo de meio de marketing, o que pode ser útil ao analisar o tráfego do aplicativo Web.

Note

Siga as melhores práticas das métricas multidimensionais ao enriquecer com tags personalizadas. As tags que são muito numerosas ou têm um intervalo não delimitado criam muitas combinações de tags, resultando em elevadas dimensões. As ferramentas de recolha têm limites nas dimensões suportadas para um contador e podem filtrar os resultados para evitar o uso excessivo de memória.

Optar por não usar métricas HTTP em certos endpoints e pedidos

Optar por não registrar métricas é benéfico para endpoints frequentemente chamados por sistemas automatizados, como verificações de integridade. O registro de métricas para essas solicitações geralmente é desnecessário. A telemetria indesejada usa recursos para coletar e armazenar e pode distorcer os resultados exibidos em um painel de telemetria.

Pode excluir pedidos HTTP para um endpoint das métricas ao adicionar metadados, com o atributo DisableHttpMetrics ou o método DisableHttpMetrics:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();

var app = builder.Build();
app.MapHealthChecks("/healthz").DisableHttpMetrics();
app.Run();

Em alternativa, a IHttpMetricsTagsFeature.MetricsDisabled propriedade foi adicionada para:

  • Cenários avançados em que uma solicitação não é mapeada para um endpoint.
  • Desativando dinamicamente a coleta de métricas para solicitações HTTP específicas.
// Middleware that conditionally opts-out HTTP requests.
app.Use(async (context, next) =>
{
    var metricsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
    if (metricsFeature != null &&
        context.Request.Headers.ContainsKey("x-disable-metrics"))
    {
        metricsFeature.MetricsDisabled = true;
    }

    await next(context);
});

Criar métricas personalizadas

Cria métricas através de APIs no espaço de nomes System.Diagnostics.Metrics. Para mais informações, consulte Criar métricas personalizadas.

Criação de métricas em aplicativos ASP.NET Core com IMeterFactory

Crie instâncias de Meter em aplicações do ASP.NET Core com IMeterFactory.

ASP.NET Core registra IMeterFactory na injeção de dependência (DI) por padrão. A fábrica de medidores integra métricas com DI, facilitando o isolamento e a coleta de métricas. IMeterFactory é especialmente útil para testes. Permite que múltiplos testes sejam executados lado a lado e só recolhe valores de métricas que são registados num teste.

Para usar IMeterFactory em um aplicativo, crie um tipo que use IMeterFactory para criar as métricas personalizadas do aplicativo:

public class ContosoMetrics
{
    private readonly Counter<int> _productSoldCounter;

    public ContosoMetrics(IMeterFactory meterFactory)
    {
        var meter = meterFactory.Create("Contoso.Web");
        _productSoldCounter = meter.CreateCounter<int>("contoso.product.sold");
    }

    public void ProductSold(string productName, int quantity)
    {
        _productSoldCounter.Add(quantity,
            new KeyValuePair<string, object?>("contoso.product.name", productName));
    }
}

Registre o tipo de métrica com DI em Program.cs:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ContosoMetrics>();

Injete o tipo de métrica e registre valores onde necessário. Como o tipo de métrica é registado em DI, pode ser usado com controladores MVC, APIs Mínimas ou qualquer outro tipo criado pela DI:

app.MapPost("/complete-sale", (SaleModel model, ContosoMetrics metrics) =>
{
    // ... business logic such as saving the sale to a database ...

    metrics.ProductSold(model.ProductName, model.QuantitySold);
});

Para monitorizar o contador "Contoso.Web", use o seguinte comando dotnet-counters.

dotnet-counters monitor -n WebMetric --counters Contoso.Web

É exibida uma saída semelhante à seguinte:

Press p to pause, r to resume, q to quit.
    Status: Running

[Contoso.Web]
    contoso.product.sold (Count / 1 sec)
        contoso.product.name=Eggs            12    
        contoso.product.name=Milk            0    

Veja métricas no Grafana com OpenTelemetry e Prometheus

Overview

OpenTelemetry:

  • É um projeto de código aberto neutro em relação ao fornecedor, suportado pela Cloud Native Computing Foundation.
  • Padroniza a geração e coleta de telemetria para software nativo da nuvem.
  • Funciona com .NET usando as APIs de métrica .NET.
  • É endossado pelo Azure Monitor e muitos fornecedores de APM.

A partir do ASP.NET Core 11, as métricas e traços do servidor HTTP incorporados do framework cumprem as partes exigidas das convenções semânticas do servidor HTTP do OpenTelemetry. A atividade de pedido do servidor HTTP emite estes atributos por defeito, correspondendo às métricas incorporadas. Como resultado, o OpenTelemetry.Instrumentation.AspNetCore pacote NuGet é opcional para recolher métricas e traços do servidor HTTP. A amostra neste artigo utiliza apenas os medidores incorporados (Microsoft.AspNetCore.Hosting e Microsoft.AspNetCore.Server.Kestrel) e não faz referência ao pacote de instrumentação. Para a lista de instrumentos incorporados e seus atributos, veja ASP.NET Core built-in HTTP metrics.

Embora o pacote seja opcional, não é um equivalente direto da instrumentação integrada. A instrumentação incorporada cobre apenas as partes necessárias das convenções semânticas. Considere as seguintes diferenças antes de remover a embalagem:

  • Alguns atributos recomendados do servidor HTTP não são emitidos pela instrumentação incorporada, como certos atributos do cliente e da rede (por exemplo, client.address). O suporte total para o atributo condicionalmente obrigatóriourl.query, incluindo a supressão, continua também em curso. Se depender destes atributos, mantenha o pacote. Para mais informações, consulte dotnet/aspnetcore#65873.
  • O pacote também facilita a ativação da telemetria além do servidor HTTP, incluindo Blazor e SignalR. Para rastreio, regista fontes de atividade adicionais para SignalR (Microsoft.AspNetCore.SignalR.Server no .NET 9 e posterior) e Blazor (Microsoft.AspNetCore.Components e Microsoft.AspNetCore.Components.Server.Circuits no .NET 10 e posterior). No caso das métricas, ativa os medidores integrados relacionados (como Microsoft.AspNetCore.Components). Sem o pacote, registe você mesmo as fontes com AddSource e os medidores com AddMeter para recolher a mesma telemetria.

Quando adicionas telemetria a uma aplicação que só precisa de métricas e rastreios do servidor HTTP, podes confiar na instrumentação incorporada e omitir o pacote. Quando atualizar uma aplicação existente de .NET 10 para .NET 11 que já faz referência ao pacote, mantenha-a se depender dos atributos, fontes ou medidores descritos na lista anterior. Ao remover o pacote, essa telemetria é perdida sem aviso.

Importante

Quando ativar o rastreio do OpenTelemetry (além das métricas) sem o pacote OpenTelemetry.Instrumentation.AspNetCore, registe o servidor HTTP do framework ActivitySource para que a atividade do pedido seja registada. A origem de atividade do servidor HTTP do ASP.NET Core tem o nome Microsoft.AspNetCore, e o framework cria uma atividade de pedido com o nome Microsoft.AspNetCore.Hosting.HttpRequestIn para cada pedido, para propagar o contexto de rastreio. Se a origem Microsoft.AspNetCore não estiver registada no SDK OpenTelemetry, a atividade da solicitação não é registada e o sampler predefinido ParentBased elimina silenciosamente quaisquer subspans personalizados iniciados durante a solicitação.

No seu pipeline de rastreamento existente, registe explicitamente a fonte:

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing => tracing
        .AddSource("Microsoft.AspNetCore")
        .AddSource("MyApp"));

No exemplo anterior:

  • AddSource("Microsoft.AspNetCore")regista a fonte de atividade HTTP do servidor ASP.NET Core para que a atividade do pedido seja registada.
  • AddSource("MyApp") regista o ActivitySource da própria aplicação. Substitua MyApp pelo nome que a sua aplicação usa.
  • Um exportador não é mostrado. Este exemplo assume que um exportador já está configurado no seu pipeline de rastreio.

Em alternativa, chama AddAspNetCoreInstrumentation() do pacote OpenTelemetry.Instrumentation.AspNetCore, que regista a origem por si.

Este tutorial mostra uma das integrações disponíveis para métricas OpenTelemetry usando os projetos OSS Prometheus e Grafana. O fluxo de dados das métricas:

  1. As APIs da métrica ASP.NET Core registram medições do aplicativo de exemplo.

  2. A biblioteca OpenTelemetry .NET em execução no aplicativo agrega as medidas.

  3. A biblioteca do exportador Prometheus disponibiliza os dados agregados através de um endpoint de métricas HTTP. 'Exportador' é o que a OpenTelemetry chama de bibliotecas que transmitem telemetria para back-ends específicos do fornecedor.

  4. Um servidor Prometheus:

    • Consulta o ponto de extremidade de métricas.
    • Lê os dados.
    • Armazena os dados em um banco de dados para persistência de longo prazo. Prometheus refere-se a ler e armazenar dados como scraping de um endpoint.
    • Pode ser executado em uma máquina diferente.
  5. O servidor Grafana:

    • Consulta os dados armazenados no Prometheus e os exibe em um painel de monitoramento baseado na Web.
    • Pode ser executado em uma máquina diferente.

Exibir métricas do aplicativo de exemplo

Aceda à aplicação de exemplo. O navegador mostra Hello OpenTelemetry! ticks:<3digits> em que 3digits são os últimos três dígitos de DateTime.Ticks atual.

Anexe /metrics à URL para exibir o ponto de extremidade da métrica. O navegador exibe as métricas que estão sendo coletadas:

métricas 2

Instalar e configurar o Prometheus

Siga os primeiros passos de Prometheus para configurar um servidor Prometheus e confirme que está a funcionar.

Modifique o ficheiro de configuração prometheus.yml para que o Prometheus recolha métricas do endpoint que a aplicação de exemplo disponibiliza. Adicione o seguinte texto realçado na secção scrape_configs:

# my global config
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]

  - job_name: 'MyASPNETApp'
    scrape_interval: 5s # Poll every 5 seconds for a more responsive demo.
    static_configs:
      - targets: ["localhost:5045"]  ## Enter the HTTP port number of the demo app.

No YAML destacado anterior, substitua 5045 pelo número de porta que a aplicação de exemplo utiliza.

Iniciar Prometheus

  1. Recarregue a configuração ou reinicie o servidor Prometheus.
  2. Confirme se o OpenTelemetryTest está no estado UP na página de Status \ Targets do portal web do Prometheus.

Prometeu estado

Selecione o ícone Abrir explorador de métricas para ver as métricas disponíveis:

Prometeu open_metric_exp

Introduza uma categoria de contadores, como http_, na caixa de entrada Expressão para ver as métricas disponíveis:

métricas disponíveis

Em alternativa, introduza uma categoria contadora, como kestrel na caixa de entrada Expressão , para ver as métricas disponíveis:

Peneireiro Prometheus

Mostrar métricas em um painel do Grafana

dashboard-screenshot2

Testar métricas em aplicativos ASP.NET Core

Podes testar métricas em aplicações ASP.NET Core. Uma forma de o fazer é recolher e afirmar valores de métricas em testes de integração ASP.NET Core usando MetricCollector<T>.

public class BasicTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;
    public BasicTests(WebApplicationFactory<Program> factory) => _factory = factory;

    [Fact]
    public async Task Get_RequestCounterIncreased()
    {
        // Arrange
        var client = _factory.CreateClient();
        var meterFactory = _factory.Services.GetRequiredService<IMeterFactory>();
        var collector = new MetricCollector<double>(meterFactory,
            "Microsoft.AspNetCore.Hosting", "http.server.request.duration");

        // Act
        var response = await client.GetAsync("/");

        // Assert
        Assert.Contains("Hello OpenTelemetry!", await response.Content.ReadAsStringAsync());

        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"]);
                Assert.Equal("/", measurement.Tags["http.route"]);
            });
    }
}

O teste anterior:

  • Inicializa uma aplicação web na memória com WebApplicationFactory<TEntryPoint>. Program no argumento genérico da fábrica especifica a aplicação web.
  • Recolhe valores de métricas com MetricCollector<T>
    • Requer uma referência de pacote para Microsoft.Extensions.Diagnostics.Testing.
    • O MetricCollector<T> é criado usando o IMeterFactoryda aplicação web. Isso permite que o coletor relate apenas os valores de métricas registrados pelo teste.
    • Inclui o nome do medidor, Microsoft.AspNetCore.Hosting, e o nome do contador, http.server.request.duration, a coletar.
  • Faz uma solicitação HTTP para o aplicativo Web.
  • Valida o teste com base nos resultados do coletor de métricas.

ASP.NET Core Identity métricas

A observabilidade do ASP.NET Core Identity ajuda-o a monitorizar as atividades de gestão de utilizadores e os processos de autenticação.

As métricas estão no Microsoft.AspNetCore.Identity medidor e são descritas nas seções a seguir.

Métricas de gerenciamento de usuários

  • aspnetcore.identity.user.create.duration Mede a duração das operações de criação de usuários.
  • aspnetcore.identity.user.update.duration Mede a duração das operações de atualização do usuário.
  • aspnetcore.identity.user.delete.duration mede a duração das operações de eliminação de utilizadores.
  • aspnetcore.identity.user.check_password_attempts Conta as tentativas de verificação de senha.
  • aspnetcore.identity.user.generated_tokens Conta tokens gerados para usuários, como tokens de redefinição de senha.
  • aspnetcore.identity.user.verify_token_attempts Conta as tentativas de verificação de token.

Métricas de autenticação

  • aspnetcore.identity.sign_in.authenticate.duration mede a duração das operações de autenticação.
  • aspnetcore.identity.sign_in.check_password_attempts Contabiliza as tentativas de verificação de palavra-passe durante o início de sessão.
  • aspnetcore.identity.sign_in.sign_ins conta inícios de sessão bem-sucedidos.
  • aspnetcore.identity.sign_in.sign_outs conta registos de saídas.
  • aspnetcore.identity.sign_in.two_factor_clients_remembered contas de clientes de autenticação de dois fatores lembradas.
  • aspnetcore.identity.sign_in.two_factor_clients_forgotten conta clientes que esqueceram a autenticação de dois fatores.

Usar estas métricas para:

  • Monitore o registro e o gerenciamento de usuários.
  • Rastreie padrões de autenticação e possíveis problemas de segurança.
  • Medir o desempenho das Identity operações.
  • Observe o uso da autenticação de dois fatores.

Visualização de Identity métricas

Use dotnet-counters para visualizar estas métricas e monitorizá-las em tempo real. Ou, exporte-os para o Prometheus e visualize-os no Grafana usando as técnicas descritas anteriormente neste artigo.

Por exemplo, para monitorizar todas as Identity métricas com dotnet-counters:

dotnet-counters monitor -n YourAppName --counters Microsoft.AspNetCore.Identity

ASP.NET Medidores e contadores de núcleo

Para uma lista de medidores e contadores do ASP.NET Core, consulte métricas ASP.NET Core. No ASP.NET Core 11 e em versões posteriores, os medidores integrados do servidor HTTP (por exemplo, Microsoft.AspNetCore.Hosting e ) emitem dados que estão em conformidade com as partes obrigatórias das Microsoft.AspNetCore.Server.Kestrel. Pode utilizar estes medidores com o SDK da OpenTelemetry sem o pacote OpenTelemetry.Instrumentation.AspNetCore.