Como correlacionar logs, métricas e traces com exemplars no Grafana
1. Fundamentos da Correlação entre Telemetrias
A observabilidade moderna enfrenta um desafio estrutural: métricas, logs e traces frequentemente vivem em silos separados. Um engenheiro que identifica um pico de latência em um gráfico precisa manualmente buscar logs e depois tentar encontrar o trace correspondente. Esse processo fragmentado consome tempo e dificulta a identificação da causa raiz.
Os exemplars surgem como a ponte entre métricas e traces. Um exemplar é uma amostra representativa de uma requisição específica que gerou um dado ponto de métrica. Ele contém o trace_id e metadados adicionais, permitindo que você clique em um ponto do gráfico e abra diretamente o trace correspondente no Grafana Tempo.
O ecossistema Grafana — composto por Loki (logs), Tempo (traces) e Mimir/Prometheus (métricas) — oferece uma plataforma unificada para essa correlação, concretizando a promessa do observability 2.0: dados interconectados com navegação fluida entre telemetrias.
2. Configuração do Stack para Suporte a Exemplars
Para habilitar exemplars, o primeiro passo é configurar o Prometheus ou VictoriaMetrics para coletar e armazenar essas amostras. No arquivo prometheus.yml, adicione a configuração de exemplars no scrape_config:
scrape_configs:
- job_name: 'meu-servico'
static_configs:
- targets: ['localhost:9090']
exemplars:
- source_labels: ['trace_id']
target_label: 'trace_id'
max_exemplars: 100
Em paralelo, configure o Grafana Tempo como backend de tracing. No docker-compose.yml, defina:
services:
tempo:
image: grafana/tempo:latest
command: ["-config.file=/etc/tempo.yaml"]
volumes:
- ./tempo.yaml:/etc/tempo.yaml
ports:
- "3200:3200" # tempo query
- "4317:4317" # otlp grpc
- "4318:4318" # otlp http
Para o Loki, ajuste a coleta de logs para incluir trace_id e span_id:
scrape_configs:
- job_name: 'logs'
pipeline_stages:
- regex:
expression: 'trace_id=(?P<trace_id>\w+)'
- labels:
trace_id:
3. Ingestão e Propagação de IDs de Contexto
A propagação correta do trace_id entre serviços é essencial. Com OpenTelemetry, você pode configurar um exporter OTLP que envia traces e métricas com exemplars simultaneamente:
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
provider = TracerProvider()
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://tempo:4317"))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("requisicao-principal") as span:
span.set_attribute("http.status_code", 200)
# O trace_id é automaticamente propagado para logs e métricas
logging.info("Requisição processada", extra={"trace_id": span.get_span_context().trace_id})
Para instrumentação automática em Node.js:
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
const { BatchSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const provider = new NodeTracerProvider();
const exporter = new OTLPTraceExporter({ url: 'http://tempo:4317' });
provider.addSpanProcessor(new BatchSpanProcessor(exporter));
provider.register();
4. Consultas e Visualização com Exemplars no Grafana
No Grafana, ao criar um painel de métricas com PromQL, os exemplars aparecem como pontos destacáveis no gráfico. Configure a consulta:
rate(http_requests_total{job="meu-servico"}[5m])
No painel, vá em Query options e ative Exemplars. Defina o data source do Tempo como destino do drill-down:
Configuração do painel:
- Data source: Prometheus
- Query: rate(http_requests_total[5m])
- Exemplars:
- Internal link: Tempo
- Trace ID label: trace_id
Ao passar o mouse sobre um ponto do gráfico, você verá os exemplars disponíveis. Clicando em um, o Grafana abre automaticamente o trace completo no Tempo, mostrando cada span e sua duração.
5. Correlação Bidirecional: Logs → Métricas → Traces
Para logs, configure derived fields no Loki. No datasource do Loki no Grafana:
Derived fields:
- Name: Trace ID
- Regex: trace_id=(\w+)
- URL/query: ${__value.raw}
- Data source: Tempo
Isso transforma automaticamente qualquer trace_id em log em um link clicável para o trace. Crie um dashboard unificado:
Dashboard "Observabilidade Unificada":
- Painel 1: Métrica de latência p99 (Prometheus)
- Painel 2: Logs recentes (Loki) com derived fields
- Painel 3: Traces recentes (Tempo)
- Variável de template: $service
Com isso, você pode navegar de um pico de latência no gráfico → clicar no exemplar → ver o trace → e acessar os logs específicos daquele trace.
6. Estratégias Avançadas e Otimização de Custos
Para reduzir volume sem perder representatividade, implemente sampling adaptativo:
# Configuração do Tempo para sampling baseado em cardinalidade
overrides:
'meu-servico':
max_bytes_per_trace: 50000
ingestion_rate_limit_bytes: 1000000
ingestion_burst_size_bytes: 2000000
Use exemplars apenas em métricas críticas:
# No Prometheus, exemplars apenas para métricas de SLO
exemplars:
- source_labels: ['trace_id']
target_label: 'trace_id'
max_exemplars: 20
# Métricas de baixa cardinalidade não precisam de exemplars
Monitore a taxa de exemplars perdidos com:
prometheus_tsdb_exemplar_exemplars_appended_total
prometheus_tsdb_exemplar_out_of_bounds_exemplars_total
7. Troubleshooting e Depuração com Exemplars
Exemplo prático: você observa um pico de latência p99 às 14:32. No painel de métricas:
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
Clique no ponto do pico → selecione o exemplar com maior duração → o Tempo abre o trace. Você identifica que o span consulta-banco levou 4.2 segundos. Acesse os logs do Loki filtrados por trace_id:
{trace_id="abc123"} |= "SELECT * FROM usuarios"
O log mostra deadlock detected. Correlação completa em segundos.
Boas práticas para evitar ruído:
- Limite exemplars para 1 a cada 1000 requisições em séries de alta cardinalidade
- Use
max_exemplarspor série temporal (padrão: 100) - Configure
exemplars_intervalpara evitar amostras muito próximas
8. Próximos Passos e Integrações Futuras
A integração com Grafana OnCall permite que alertas disparados por métricas incluam links diretos para traces:
# Configuração de alerta com link para trace
- alert: HighLatency
expr: histogram_quantile(0.99, ...) > 2
annotations:
summary: "Latência alta detectada"
runbook_url: "https://runbook.exemplo.com"
trace_link: "http://grafana:3000/explore?orgId=1&left=%7B%22datasource%22:%22Tempo%22,%22queries%22:%5B%7B%22queryType%22:%22traceId%22,%22query%22:%22${trace_id}%22%7D%5D%7D"
Para SLO burn rate, crie painéis que mostram exemplars dos traces que contribuíram para o erro:
slo:http_errors:ratio_rate5m{job="meu-servico"} > 0.01
O roadmap do Grafana inclui correlação automática com machine learning, onde anomalias em métricas serão automaticamente vinculadas a traces suspeitos, reduzindo ainda mais o tempo de diagnóstico.
Referências
-
Grafana Exemplars Documentation — Guia oficial sobre configuração e uso de exemplars no Grafana, com exemplos práticos de drill-down entre métricas e traces.
-
Prometheus Exemplars Configuration — Documentação oficial do Prometheus sobre configuração de exemplars, incluindo parâmetros de scraping e limites de armazenamento.
-
OpenTelemetry Trace Context Propagation — Fundamentos da propagação de contexto de tracing, essencial para garantir que trace_ids cheguem corretamente a logs e métricas.
-
Grafana Tempo Documentation - Exemplars — Guia específico do Tempo para integração com exemplars, incluindo configuração de sampling e visualização.
-
Loki Derived Fields Configuration — Como configurar derived fields no Loki para extrair automaticamente trace_ids de logs e criar links para o Tempo.
-
Grafana Blog - Observability 2.0 with Exemplars — Artigo técnico detalhando a evolução da observabilidade com exemplars, casos de uso reais e melhores práticas.
-
Prometheus Exemplars: A Practical Guide — Tutorial prático de Brian Brazil sobre implementação de exemplars no Prometheus, incluindo troubleshooting e otimização.