Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 58

OpenTelemetry for Application Metrics

Recommended resources

Olá! Bem-vindo de volta à nossa jornada pela observabilidade no .NET Aspire.

Nas lições anteriores, exploramos os dois primeiros pilares da observabilidade. Primeiro, mergulhamos nos logs estruturados para capturar eventos detalhados e, em seguida, desvendamos os traces distribuídos para visualizar a jornada completa de uma requisição através de múltiplos serviços.

Hoje, vamos completar a tríade com o terceiro pilar: Métricas. Nosso objetivo é: Expor e monitorar métricas padrão e personalizadas de aplicações usando o OpenTelemetry. Enquanto logs e traces são excelentes para investigar eventos ou requisições individuais, as métricas nos dão uma visão agregada e quantitativa da saúde e do desempenho do nosso sistema ao longo do tempo. Elas respondem a perguntas como: "Qual é a taxa de requisições por segundo?" ou "Qual foi o tempo médio de resposta da minha API na última hora?".

O Que São Métricas?

Métricas são medições numéricas coletadas em intervalos de tempo. No ecossistema .NET, a API System.Diagnostics.Metrics é a base para criar e registrar essas medições. O OpenTelemetry então coleta essas medições e as exporta para uma ferramenta de visualização, como o Aspire Dashboard.

Métricas Padrão (Built-in)

Muitas bibliotecas do .NET, incluindo o próprio ASP.NET Core, já vêm com instrumentação embutida que expõe uma variedade de métricas úteis por padrão. O .NET Aspire, através da sua configuração de ServiceDefaults, habilita a coleta dessas métricas automaticamente.

Isso significa que, sem escrever uma única linha de código de instrumentação, você já tem acesso a dados valiosos sobre o seu aplicativo.

.NET Aspire Dashboard: HTTP Server Duration Metrics
Esta imagem do Aspire Dashboard mostra a métrica padrão `http.server.duration`. Ela exibe a duração das requisições HTTP ao longo do tempo, dividida em percentis (P50, P90, P99), que são essenciais para entender a experiência do usuário sob diferentes cargas.

Outras métricas padrão incluem:

  • aspnetcore.requests.active: O número de requisições HTTP ativas.
  • kestrel.connections.active: O número de conexões ativas no servidor Kestrel.
  • system.runtime.alloc.rate: A taxa de alocação de memória no heap.

Criando Métricas Personalizadas

Métricas padrão são ótimas, mas o verdadeiro poder vem de medir o que é único e importante para o seu domínio de negócio. Quer contar o número de pedidos processados, produtos adicionados a um carrinho ou falhas de login? Para isso, você precisa de métricas personalizadas.

O processo para criar uma métrica personalizada em .NET envolve três etapas principais:

  1. Criar um Meter: Um Meter é uma classe que serve como um "agrupador" ou uma fábrica para os seus instrumentos. É uma boa prática criar um Meter por biblioteca ou por componente lógico da sua aplicação, dando a ele um nome único.
  2. Criar um Instrument: A partir do Meter, você cria um instrumento específico. Existem vários tipos, cada um para um propósito diferente. Os mais comuns são Counter e Histogram.
  3. Registrar Medições: No seu código de aplicação, você chama métodos no instrumento para registrar medições (por exemplo, Add() para um Counter ou Record() para um Histogram).

Vamos ver isso na prática. O vídeo a seguir, do canal de Milan Jovanović, demonstra de forma concisa como adicionar uma métrica personalizada para contar o número de vendas em uma API.

A practical introduction to OpenTelemetry for .NET developers (+ Aspire Dashboard)

Para entender o fluxo completo, desde a criação da métrica até sua visualização, assista a este segmento do vídeo 'A practical introduction to OpenTelemetry for .NET developers'.

Assista do timestamp 11:21 até 13:46. Preste atenção em como ele: Cria uma classe estática para definir o Meter e o Counter<int> para sales.count. Adiciona o nome do Meter personalizado à configuração do OpenTelemetry com AddMeter(). Incrementa o contador com _salesCounter.Add(1) no ponto relevante do código. Adiciona tags (dimensões) à medição, como coffee.type e sale.id, para permitir uma análise mais granular. Finalmente, mostra a métrica personalizada e os filtros de tags no Aspire Dashboard.

Adicionando Dimensões com Tags

Como visto no vídeo, um dos recursos mais poderosos das métricas é a capacidade de adicionar tags (também conhecidas como atributos ou dimensões). São pares de chave-valor que você anexa a uma medição. Isso permite que você filtre e agrupe seus dados em uma ferramenta de visualização.

Em vez de ter apenas uma métrica sales.count, você pode ter sales.count dividida por product_category, region ou payment_method. Isso transforma uma simples contagem em uma ferramenta de análise de negócios.

.NET Aspire Dashboard: Custom Metrics Monitoring
Nesta imagem, vemos uma métrica personalizada `notes.count` no Aspire Dashboard. As tags, como `note.id`, permitem filtrar os dados para visualizar a contagem de notas específicas, tornando a métrica muito mais útil para depuração e análise.

Escolhendo o Instrumento Certo

A API System.Diagnostics.Metrics oferece vários tipos de instrumentos. Saber qual usar é fundamental para coletar dados significativos.

Para uma exploração aprofundada, a documentação oficial da Microsoft é o melhor recurso.

Creating Metrics - .NET

A documentação 'Creating Metrics' da Microsoft detalha os diferentes tipos de instrumentos e suas melhores práticas de uso. É uma leitura essencial para solidificar seu entendimento.

Foque na leitura da seção 'Types of instruments'. Entenda a diferença entre cada um dos seguintes instrumentos e para que tipo de cenário cada um é mais adequado.

Aqui está um resumo prático dos principais instrumentos:

Instrumento Propósito Exemplo de Uso
Counter<T> Rastreia um valor que sempre aumenta. Número total de requisições, vendas realizadas, erros registrados.
UpDownCounter<T> Rastreia um valor que pode aumentar e diminuir. Número de conexões ativas, itens em uma fila, usuários logados no momento.
Histogram<T> Rastreia a distribuição estatística de um conjunto de medições. Duração de requisições, tamanho de payloads, tempo de processamento de uma tarefa. Permite calcular médias, e mais importante, percentis (P50, P90, P99).
ObservableGauge<T> Representa um valor que é medido em um ponto específico no tempo, obtido através de um callback. Temperatura atual da CPU, uso de memória atual.

Um Padrão Elegante para Medir Duração: Histogram com IDisposable

Medir a duração das operações é um caso de uso muito comum para Histogram. Há um padrão de design particularmente elegante para isso em C# que usa IDisposable e o using statement. Dado seu background em C#, você apreciará essa abordagem.

O vídeo a seguir, do canal de Nick Chapsas, demonstra esse padrão de forma brilhante.

Measure Your Application’s Performance in .NET

No vídeo 'Measure Your Application’s Performance in .NET', Nick Chapsas implementa uma medição de duração de requisição usando um padrão com IDisposable.

Assista do timestamp 09:15 até 11:21. O foco aqui não é apenas o Histogram, mas o padrão de implementação: Ele cria uma classe TrackRequestDuration que implementa IDisposable. O construtor da classe captura o Stopwatch.GetTimestamp() inicial. O método Dispose() calcula o tempo decorrido e chama _histogram.Record(). No endpoint da API, ele simplesmente envolve a lógica com using (metrics.MeasureRequestDuration()). Isso garante que a medição de duração seja registrada automaticamente no final do escopo, mesmo que ocorram exceções. É um padrão limpo e robusto.

Teste seu entendimento!

Você está instrumentando uma aplicação de e-commerce e precisa adicionar as seguintes métricas personalizadas. Para cada cenário, qual tipo de instrumento da API System.Diagnostics.Metrics seria o mais apropriado?

  1. Contar o número de vezes que um usuário adiciona um item ao carrinho.
  2. Medir o tempo que leva para processar um pagamento, com o objetivo de entender não apenas a média, mas também os casos mais lentos (outliers).
  3. Acompanhar o número de produtos atualmente em estoque para um determinado item. O estoque aumenta com o reabastecimento e diminui com as vendas.
Show answer
  1. Counter<int>: Este é um evento que só acumula. O valor total de "itens adicionados ao carrinho" só pode aumentar.
  2. Histogram<double>: Para medir a duração e entender a distribuição, o Histogram é a escolha perfeita. Ele permitirá que você calcule a média, mas, mais importante, os percentis como P95 e P99 para identificar os pagamentos mais lentos que afetam a experiência do usuário.
  3. UpDownCounter<int>: Como o valor do estoque pode tanto aumentar (reabastecimento) quanto diminuir (vendas), o UpDownCounter é o instrumento ideal para rastrear essa métrica flutuante.

Conclusão

Nesta lição, exploramos o terceiro e último pilar da observabilidade: as métricas. Vimos como elas fornecem uma visão agregada e de alto nível da saúde do nosso sistema, complementando os detalhes granulares fornecidos por logs e traces.

Principais Pontos:

  • As métricas são medições numéricas agregadas ao longo do tempo, cruciais para monitorar tendências de desempenho e saúde.
  • .NET Aspire coleta métricas padrão (como http.server.duration) automaticamente, fornecendo insights imediatos.
  • Para monitorar lógicas de negócio específicas, criamos métricas personalizadas usando a API System.Diagnostics.Metrics (Meter, Instrument).
  • Tags (dimensões) são essenciais para fatiar e analisar os dados das métricas, transformando-as em poderosas ferramentas analíticas.
  • A escolha do instrumento correto (Counter, Histogram, UpDownCounter, etc.) é fundamental para coletar dados significativos e apropriados para cada cenário.

Próxima Lição:
Com um entendimento sólido dos três pilares da observabilidade (logs, traces e métricas), estamos bem equipados para monitorar e depurar nossas aplicações. Na próxima lição, vamos focar em um aspecto mais proativo do monitoramento: health checks (verificações de saúde). Aprenderemos como configurar verificações de saúde personalizadas para nossos serviços no Aspire e como visualizar seu status, permitindo que sistemas de orquestração (como o Kubernetes) reajam automaticamente a serviços que não estão saudáveis.