Instrumentação .NET com Elven Observability

Guia completo para adicionar traces, métricas e logs às aplicações .NET modernas usando a distribuição OpenTelemetry da Elven.

Sumário

  • Visão geral

  • Pré-requisitos

  • Caminho recomendado

  • Quick Start - Docker zero-code (recomendado)

  • Quick Start - Zero-code no processo

  • Pacotes NuGet (para uso programático)

  • Quick Start - ASP.NET Core programático

  • Quick Start - Worker Service programático

  • Quick Start - Console app

  • Configuração por variáveis de ambiente

  • Configuração via appsettings.json

  • Deploy com Docker

  • Guia por tipo de aplicação

  • Usando logs, traces e métricas manuais

  • Instrumentações automáticas

  • Mapeamento de erros

  • Recursos e metadados

  • Configuração avançada

  • Native AOT e trimming

  • Validação ponta a ponta

  • Boas práticas

  • Troubleshooting

  • FAQ


Visão geral

A instrumentação .NET da Elven é uma distribuição OpenTelemetry pronta para produção. Ela configura o SDK oficial do OpenTelemetry .NET com os padrões da Elven Observability para o stack LGTM:

  • Grafana Loki para logs

  • Grafana Tempo para traces

  • Grafana Mimir para métricas

  • Grafana para visualização, correlação e alertas

Componente
O que faz

Elven.Observability

Pacote principal. Instale este na maioria dos projetos.

Elven.Observability.Hosting

Extensões para IHostApplicationBuilder e IServiceCollection.

Elven.Observability.AspNetCore

Extensões ASP.NET Core, middleware de erros e health check.

Elven.Observability.AutoInstrumentation

Plugin para zero-code instrumentation com o CLR profiler do OpenTelemetry.

elvenobservability/dotnet-instrumentation

Imagem Docker com a camada de auto-instrumentação pronta para uso.

Importante: em modo Elven, logs, métricas e traces ficam sempre ligados. Configurações que tentam desligar um sinal, como OTEL_LOGS_EXPORTER=none, são tratadas como erro de configuração.

Arquitetura: o Collector OTLP fica sempre do lado do cliente: Kubernetes, ECS, VM, Docker Compose, appliance interno ou outro ambiente gerenciado pelo cliente. A aplicação .NET envia OTLP para esse Collector do cliente, e ele encaminha para os backends Elven.


Pré-requisitos

  • .NET 8 LTS, .NET 9 ou .NET 10

  • Aplicações ASP.NET Core, Worker Services, Generic Host, console apps, gRPC, serviços em container ou jobs

  • Collector OTLP implantado no ambiente do cliente

  • Credenciais da Elven Observability:

    • Tenant ID

    • API Token

    • Endpoint OTLP do Collector do cliente

Protocolos suportados

Protocolo
Valor
Uso recomendado

OTLP gRPC

grpc

Padrão recomendado para aplicações .NET.

OTLP HTTP/protobuf

http/protobuf

Útil em ambientes que bloqueiam gRPC ou exigem HTTP.

Targets suportados

Target framework
Status

net8.0

Suportado, base mínima LTS.

net9.0

Suportado.

net10.0

Suportado.


Caminho recomendado

Comece sempre pelo caminho com menor atrito operacional. A ideia é instrumentar primeiro, validar os três sinais no Grafana e só depois decidir se precisa de customização no código.

Prioridade
Caminho
Quando usar

1

Docker zero-code com env vars

Recomendado para a maioria dos serviços containerizados. Não exige alterar o código.

2

Zero-code no processo

Bom para VM, systemd, processos dotnet diretos e ambientes sem rebuild da imagem.

3

Programático ASP.NET Core / Worker

Use quando precisa de spans, métricas, health check e políticas customizadas no código.

4

Console/manual

Use para jobs curtos, CLIs e aplicações sem Host/DI.

O endpoint OTLP usado nos exemplos deve apontar para o Collector do cliente, não para um collector compartilhado da Elven.


Quick Start - Docker zero-code (recomendado)

Este é o caminho preferencial para aplicações .NET em container. A aplicação não precisa instalar o pacote NuGet nem alterar Program.cs; a camada elvenobservability/dotnet-instrumentation injeta o CLR profiler do OpenTelemetry e o plugin da Elven.

1. Adicione a camada Elven no Dockerfile

2. Configure por variáveis de ambiente

3. Gere tráfego e valide

No Grafana, procure pelo service.name configurado em OTEL_SERVICE_NAME.


Quick Start - Zero-code no processo

Use este modo em VM, systemd, shells, CI ou qualquer ambiente onde a aplicação roda com dotnet MinhaAplicacao.dll e você não quer alterar o código.

Native AOT não suporta CLR profiler. Para Native AOT, use inicialização programática.

Linux/macOS

Windows PowerShell

Variáveis principais do profiler

Em ambientes automatizados, confirme se as variáveis abaixo estão presentes:

Variável
Valor Linux comum

CORECLR_ENABLE_PROFILING

1

CORECLR_PROFILER

{918728DD-259F-4A6A-AC2B-B85E1B658318}

CORECLR_PROFILER_PATH

/otel/current/OpenTelemetry.AutoInstrumentation.Native.so

DOTNET_ADDITIONAL_DEPS

/otel/AdditionalDeps

DOTNET_SHARED_STORE

/otel/store

DOTNET_STARTUP_HOOKS

/otel/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll

OTEL_DOTNET_AUTO_HOME

/otel

OTEL_DOTNET_AUTO_PLUGINS

Elven.Observability.AutoInstrumentation.ElvenPlugin, Elven.Observability.AutoInstrumentation


Pacotes NuGet (para uso programático)

Esta etapa só é necessária quando você quer configurar a observabilidade pelo código, por exemplo com builder.AddElvenObservability(...) ou ElvenObservability.Initialize(...). Para Docker zero-code ou profiler zero-code, pule esta seção.

Instalação básica

Verificar instalação

Pacotes disponíveis

Na maioria dos casos, use apenas Elven.Observability. Os pacotes abaixo existem para cenários avançados, composição manual ou redução explícita de dependências:

Pacote
Quando usar

Elven.Observability

Facade principal para aplicações comuns.

Elven.Observability.Abstractions

Contratos, opções e nomes estáveis.

Elven.Observability.Core

Resolver de configuração, resource detector, erro e telemetria manual.

Elven.Observability.Hosting

Aplicações com Generic Host ou DI.

Elven.Observability.AspNetCore

ASP.NET Core, middleware e health check.

Elven.Observability.Exporters.Otlp

Defaults Elven para OTLP.

Elven.Observability.AutoInstrumentation

Plugin zero-code.

Elven.Observability.Instrumentation.Sql

SQL Client.

Elven.Observability.Instrumentation.EntityFrameworkCore

Entity Framework Core.

Elven.Observability.Instrumentation.Redis

StackExchange.Redis.

Elven.Observability.Instrumentation.MongoDB

MongoDB via ActivitySource.

Elven.Observability.Instrumentation.Messaging

Kafka, RabbitMQ e MassTransit via sources/meters.

Elven.Observability.Instrumentation.Cloud

AWS SDK e Azure SDK via sources/meters.


Quick Start - ASP.NET Core programático

1. Instale o pacote

2. Configure as variáveis de ambiente

3. Adicione a instrumentação no Program.cs

4. Rode a aplicação

Pronto. A aplicação já envia traces, métricas e logs por OTLP.


Quick Start - Worker Service programático

Use este modo para consumidores, filas, jobs long-running, processadores de eventos e serviços sem HTTP.


Quick Start - Console app

Use a API estática quando a aplicação não usa DI, Host ou ASP.NET Core.

Para jobs curtos, chame ForceFlushAsync() antes de encerrar o processo. Isso evita perder spans, métricas ou logs que ainda estejam em buffer.


Configuração por variáveis de ambiente

A configuração segue os padrões OpenTelemetry e adiciona extensões Elven.

Identidade do serviço

Variável
Descrição
Exemplo

OTEL_SERVICE_NAME

Nome do serviço em traces, métricas e logs.

checkout-api

OTEL_SERVICE_VERSION

Versão da aplicação.

1.4.2

ELVEN_SERVICE_NAMESPACE

Namespace lógico do serviço.

payments

ELVEN_ENVIRONMENT

Ambiente de deploy. Popula deployment.environment.name.

production

ELVEN_REGION

Região lógica ou cloud region.

sa-east-1

OTEL_RESOURCE_ATTRIBUTES

Atributos adicionais separados por vírgula.

team=core,service.instance.id=pod-1

Export OTLP

Variável
Descrição
Default

OTEL_EXPORTER_OTLP_ENDPOINT

Endpoint OTLP do Collector do cliente para os três sinais.

Configure explicitamente

ELVEN_OTLP_ENDPOINT

Alias Elven para o endpoint OTLP.

-

OTEL_EXPORTER_OTLP_PROTOCOL

grpc ou http/protobuf.

grpc

OTEL_EXPORTER_OTLP_HEADERS

Headers extras no formato key=value,key2=value2.

-

OTEL_EXPORTER_OTLP_TIMEOUT

Timeout de export em ms.

30000

OTEL_METRIC_EXPORT_INTERVAL

Intervalo de export de métricas em ms.

60000

Autenticação e multi-tenancy

Variável
Mapeamento

ELVEN_API_KEY

Enviado como header Authorization: Bearer <token>.

ELVEN_TENANT_ID

Enviado como header x-scope-orgid: <tenant>.

Também é possível usar OTEL_EXPORTER_OTLP_HEADERS, mas prefira ELVEN_API_KEY e ELVEN_TENANT_ID para evitar erro de formatação:

Política de sinais sempre ligados

Variável
Valor correto

OTEL_TRACES_EXPORTER

otlp

OTEL_METRICS_EXPORTER

otlp

OTEL_LOGS_EXPORTER

otlp

Os valores abaixo são inválidos em modo Elven:

Quando isso acontece, a aplicação falha no startup com uma mensagem explícita e o health check de observabilidade fica Unhealthy.

Sampling

Variável
Descrição
Exemplo

OTEL_TRACES_SAMPLER

always_on ou sampler compatível.

always_on

OTEL_TRACES_SAMPLER_ARG

Ratio de sampling quando aplicável.

0.25

O SamplingRatio precisa ser maior que 0 e menor ou igual a 1.

Debug

Variável
Descrição

ELVEN_DEBUG

Quando true, 1 ou equivalente, habilita diagnósticos internos mais verbosos.


Configuração via appsettings.json

A lib lê a seção ElvenObservability. Também aceita Elven:Observability para compatibilidade com padrões hierárquicos.

Não grave ApiKey em appsettings.json versionado. Use secret manager, variável de ambiente, cofre de segredo ou mecanismo equivalente da sua plataforma.

Ordem de precedência

A resolução segue esta ordem:

  1. Defaults Elven

  2. appsettings.json

  3. Variáveis de ambiente

  4. Configuração programática passada no AddElvenObservability(...)


Deploy com Docker

Modo zero-code com camada Elven

Use este modo como padrão para serviços containerizados. Ele não exige alteração no código da aplicação.

Docker Compose zero-code

Modo programático

Use este modo quando o pacote NuGet está instalado na aplicação e você quer manter a instrumentação no código.

Passe ELVEN_API_KEY como segredo no runtime, não no Dockerfile:


Guia por tipo de aplicação

ASP.NET Core Web API

Use:

O que é coletado:

  • Requests HTTP server

  • Route template em http.route

  • Status code

  • Duração

  • Exceções

  • Logs de ILogger

  • Correlação trace_id e span_id

  • Métricas ASP.NET Core e Kestrel

Minimal APIs

Funciona sem configuração extra:

MVC e Controllers

Também funciona sem configuração extra:

gRPC

Instale e configure o serviço normalmente:

O client gRPC via Grpc.Net.Client é instrumentado automaticamente quando EnableGrpcClientInstrumentation=true.

Worker Service

Use Host.CreateApplicationBuilder(args) e builder.AddElvenObservability(). Crie spans manuais ao redor de cada unidade de trabalho relevante:

Jobs curtos

Sempre finalize com flush:

Lambda e Azure Functions

Para funções com processo .NET moderno, prefira inicialização programática no bootstrap da aplicação ou no host isolado. Em execução curta, garanta flush no final do handler quando possível.


Usando logs, traces e métricas manuais

A instrumentação automática cobre o caminho comum. Para regras de negócio, adicione telemetria manual em pontos relevantes.

Logs estruturados

Use ILogger normalmente:

A lib exporta:

  • Mensagem formatada

  • Template original

  • Propriedades estruturadas

  • Scopes

  • trace_id e span_id quando houver span ativo

Source-generated logging

Para caminhos quentes, prefira LoggerMessage:

Spans manuais

Eventos no span

Métricas customizadas

Baggage e propagação

O OpenTelemetry .NET usa W3C TraceContext e Baggage. Para propagar contexto de negócio entre serviços:


Instrumentações automáticas

Traces

Área
Cobertura

ASP.NET Core

Requests, route, status, duração, exceções.

HttpClient

Requests outbound, status, duração, exceções.

gRPC client

Chamadas Grpc.Net.Client.

SQL Client

Queries, comandos, exceções.

Entity Framework Core

Operações EF Core.

Redis

StackExchange.Redis, statements opcionais.

AWS SDK

ActivitySource oficial do AWS SDK.

Azure SDK

ActivitySource dos clients Azure.

MongoDB

Source registration para integração via diagnostic sources.

Kafka

Source registration para Confluent.Kafka.Extensions.OpenTelemetry.

RabbitMQ

Source registration para RabbitMQ.Client.

MassTransit

Source e meter registration.

Manual

ElvenTelemetry.ActivitySource.

Métricas

Área
Cobertura

Runtime .NET

GC, heap, allocations, exceptions, threadpool, JIT e runtime.

Process

CPU, memória, threads e handles quando disponível.

ASP.NET Core/Kestrel

Requests, conexões e métricas do servidor.

HttpClient

Duração, DNS, TLS e conexões via meters do .NET.

SQL

Métricas do provider quando disponíveis.

AWS

Métricas oficiais disponíveis pelo pacote.

Custom

ElvenTelemetry.Meter.

Internas Elven

Misconfigurações, falhas de exporter e erros classificados.

Logs

Fonte
Cobertura

ILogger

Logs estruturados, scopes e state values.

ASP.NET Core

Logs do pipeline HTTP e endpoints.

Aplicação

Logs de negócio com correlação automática.

Elven

Logs internos de classificação e diagnóstico.


Mapeamento de erros

O middleware UseElvenObservability() e o classificador interno adicionam error.category e error.type aos spans.

Caso
Categoria

OperationCanceledException

cancelled

TimeoutException

timeout

SocketError.HostNotFound, NoData, TryAgain

dns

SocketError.ConnectionRefused

connection_refused

HttpRequestException com certificado/nome remoto suspeito

dns_poisoning

DbException, Npgsql, MySql, Mongo, Redis, SqlClient

database

UnauthorizedAccessException

auth

FluentValidation/DataAnnotations/ValidationException

validation

ArgumentException, FormatException, JsonException

user_input

Erro de configuração no startup

configuration

HTTP 401, 403

auth

HTTP 422

validation

HTTP 400, 404, 405, 409

user_input_error

Outros HTTP 4xx

client_error

HTTP 5xx

server_error

gRPC CANCELLED

cancelled

gRPC DEADLINE_EXCEEDED

timeout

gRPC UNAUTHENTICATED, PERMISSION_DENIED

auth

gRPC INVALID_ARGUMENT, FAILED_PRECONDITION, OUT_OF_RANGE

validation

gRPC UNAVAILABLE

network

gRPC INTERNAL, DATA_LOSS, UNKNOWN

server_error

Exemplo de endpoint com erro


Recursos e metadados

A lib popula resource attributes seguindo semantic conventions estáveis.

Atributo
Origem

service.name

OTEL_SERVICE_NAME ou ServiceName.

service.namespace

ELVEN_SERVICE_NAMESPACE ou ServiceNamespace.

service.version

OTEL_SERVICE_VERSION ou ServiceVersion.

service.instance.id

ServiceInstanceId ou OTEL_RESOURCE_ATTRIBUTES.

deployment.environment.name

ELVEN_ENVIRONMENT ou EnvironmentName.

host.name

Environment.MachineName.

host.id

/etc/machine-id, /var/lib/dbus/machine-id ou boot id quando disponível.

container.id

Detectado a partir de /proc/self/cgroup quando disponível.

k8s.namespace.name

POD_NAMESPACE, KUBERNETES_NAMESPACE ou service account namespace.

k8s.pod.name

HOSTNAME.

k8s.pod.uid

POD_UID.

k8s.node.name

NODE_NAME.

k8s.cluster.name

CLUSTER_NAME.

process.runtime.name

.NET.

process.runtime.version

Versão do runtime.

telemetry.distro.name

elven-observability-dotnet.

telemetry.distro.version

Versão da lib Elven.

elven.tenant.id

ELVEN_TENANT_ID ou TenantId.

elven.environment

ELVEN_ENVIRONMENT ou EnvironmentName.

elven.region

ELVEN_REGION ou Region.


Configuração avançada

Configuração programática completa

Opções principais

Opção
Default
Descrição

ServiceName

unknown-service

Nome do serviço.

ServiceNamespace

default

Namespace lógico.

Endpoint

Collector do cliente

Endpoint OTLP para envio dos três sinais.

Protocol

Grpc

Grpc ou HttpProtobuf.

SamplingRatio

1.0

Ratio de traces. Precisa ser maior que 0.

ExporterTimeout

30s

Timeout do exporter.

MetricExportInterval

60s

Intervalo de export de métricas.

RedactDbStatements

true

Redacta statements de banco quando suportado.

RedactHeaders

true

Política de privacidade para headers.

RedactUrlQuery

true

Evita vazamento de query strings sensíveis.

HashUserIdentifiers

true

Política para identificadores de usuário.

CaptureRequestHeaders

false

Captura headers permitidos em spans HTTP.

CaptureResponseHeaders

false

Captura headers permitidos em spans HTTP.

EnableHealthCheck

true

Habilita health check de observabilidade.

Headers HTTP

Headers só são capturados quando:

  1. CaptureRequestHeaders ou CaptureResponseHeaders está true

  2. O header está na allowlist correspondente

Os nomes são normalizados para atributos OTel:

Header
Atributo

x-request-id

http.request.header.x_request_id

user-agent

http.request.header.user_agent

x-elven-response

http.response.header.x_elven_response

HTTP/protobuf

Ou programático:

Redação de statements SQL

Por padrão, statements de banco são redigidos.

Para diagnóstico temporário:

Use statements completos apenas em ambientes controlados. Queries podem conter dados pessoais, tokens ou payloads sensíveis.


Native AOT e trimming

A inicialização programática é compatível com Native AOT e trimming onde o SDK OpenTelemetry e as instrumentações oficiais permitem.

Recomendações para AOT

  • Use inicialização programática com builder.AddElvenObservability()

  • Evite zero-code instrumentation, pois CLR profiler não se aplica a Native AOT

  • Desabilite instrumentações que dependem de reflexão se o publish acusar warnings

  • Mantenha TreatWarningsAsErrors=true no projeto

Exemplo:

Publish:

Ajustes comuns para AOT


Validação ponta a ponta

1. Crie um endpoint de teste

2. Gere tráfego

3. Gere uma exceção controlada

4. Valide no Grafana

No Grafana, procure por:

  • Serviço service.name

  • Route HTTP

  • trace_id retornado no endpoint

  • Logs com o mesmo trace_id

  • Métricas customizadas

  • Span com error.category

  • Resource attributes como deployment.environment.name, service.namespace e elven.tenant.id

5. Health check

Resposta esperada:


Boas práticas

Nome de serviço

Use nomes estáveis, curtos e sem ambiente no nome:

Evite:

Cardinalidade

Não use valores de alta cardinalidade como labels de métricas:

  • IDs de usuário

  • IDs de pedido

  • Emails

  • Tokens

  • URLs completas com query string

Use esses valores em spans ou logs, com cuidado de privacidade.

Logs

Prefira logs estruturados:

Evite interpolação em logs de caminho quente:

Segurança

  • Não coloque ELVEN_API_KEY no código

  • Não versionar tokens em appsettings.json

  • Redactar statements SQL por padrão

  • Capturar headers apenas com allowlist

  • Evitar payload bruto em spans e logs

Performance

  • Use LoggerMessage em caminhos muito chamados

  • Evite spans manuais em loops internos de altíssima frequência

  • Use histogramas para latência de negócio

  • Ajuste SamplingRatio com cuidado

  • Mantenha métricas com baixa cardinalidade


Troubleshooting

Nenhum dado aparece no Grafana

Verifique:

Confirme que:

  • OTEL_TRACES_EXPORTER=otlp

  • OTEL_METRICS_EXPORTER=otlp

  • OTEL_LOGS_EXPORTER=otlp

  • ELVEN_API_KEY está configurado

  • ELVEN_TENANT_ID está correto

  • A aplicação consegue acessar o endpoint OTLP

Erro de autenticação

ELVEN_API_KEY é enviado como Bearer automaticamente:

Não inclua a palavra Bearer dentro da variável. A lib monta o header final:

Erro de tenant

Configure:

A lib monta:

A aplicação falha no startup com exporter none

Em modo Elven, os três sinais são obrigatórios. Remova valores none:

Ou defina explicitamente:

gRPC não conecta

Se o ambiente bloqueia gRPC, use HTTP/protobuf:

Confirme também se o endpoint aceita o protocolo escolhido.

Logs aparecem sem trace_id

Logs só recebem correlação quando há Activity.Current. Em ASP.NET Core isso acontece automaticamente dentro de requests. Em Workers e Console apps, crie um span manual:

Headers não aparecem nos spans

Confirme a allowlist:

Procure o atributo com _ no lugar de -:

Statements SQL não aparecem

Por padrão, statements são redigidos quando a instrumentação suporta essa opção. Para diagnóstico temporário:

Health check unhealthy

Consulte /health/observability. O motivo mais comum é uma misconfiguração no startup, como:

  • Endpoint OTLP inválido

  • Sampling ratio 0

  • Exporter none

  • OTEL_TRACES_SAMPLER=always_off

Auto-instrumentation não carrega

Verifique:

Confirme que o arquivo apontado por CORECLR_PROFILER_PATH existe e que a aplicação não está publicada como Native AOT.


FAQ

Preciso configurar logs, métricas e traces separadamente?

Não. A chamada AddElvenObservability() configura os três sinais.

Posso desligar logs, métricas ou traces?

Não em modo Elven. A plataforma espera os três sinais para correlação completa. Configurações como OTEL_LOGS_EXPORTER=none são tratadas como erro.

O protocolo padrão é qual?

grpc.

Posso usar HTTP/protobuf?

Sim. Configure:

O pacote substitui o OpenTelemetry SDK?

Não. Ele configura e padroniza o SDK oficial do OpenTelemetry .NET para a Elven Observability.

Funciona com .NET Framework 4.x?

Não. O foco é .NET moderno: net8.0, net9.0 e net10.0.

Funciona com Native AOT?

Sim para inicialização programática, respeitando as limitações das instrumentações oficiais usadas no projeto. Zero-code via CLR profiler não se aplica a Native AOT.

Como envio dados de negócio?

Use ElvenTelemetry.ActivitySource para spans e ElvenTelemetry.Meter para métricas customizadas. Use ILogger para logs estruturados.

Como correlacionar logs e traces?

Dentro de uma request ASP.NET Core ou de um span manual, ILogger é exportado com contexto de trace e span automaticamente.

Como configuro multi-tenancy?

Use:

A lib envia esse valor no header x-scope-orgid.

Como configuro autenticação?

Use:

A lib envia esse valor como Authorization: Bearer <token>.

Qual imagem Docker devo usar para zero-code?

Use:

Como vejo se está funcionando?

Faça uma request na aplicação, gere um log e consulte no Grafana pelo service.name. Para ASP.NET Core, também valide:

Last updated

Was this helpful?