Observabilidade com Grafana Stack: Loki, Tempo e Mimir na prática
1. Introdução à Grafana Stack para Observabilidade
Em um cenário de sistemas distribuídos cada vez mais complexos, a capacidade de correlacionar logs, traces e métricas tornou-se requisito fundamental para equipes que buscam confiabilidade. A Grafana Stack — composta por Loki, Tempo e Mimir — oferece uma plataforma unificada e de código aberto que resolve esse desafio sem a necessidade de múltiplas ferramentas desconectadas.
Diferente de soluções como Prometheus + Jaeger + Elastic, que exigem integrações manuais e custos elevados de armazenamento, a stack Grafana foi projetada para trabalhar de forma integrada desde a concepção. Loki gerencia logs com eficiência usando índices invertidos baseados em labels, Tempo armazena traces distribuídos com baixo custo de armazenamento, e Mimir oferece métricas de longa retenção com escalabilidade horizontal nativa.
2. Loki: Agregação de Logs em Escala
Loki difere de soluções tradicionais como Elasticsearch por não indexar o conteúdo completo dos logs. Em vez disso, utiliza labels para indexação e armazena os logs em chunks comprimidos em object stores (S3, GCS, MinIO). Isso reduz drasticamente o custo de armazenamento e acelera consultas.
Para coletar logs, utilizamos o Promtail (ou o novo Alloy). Um exemplo de configuração básica do Promtail:
# promtail-config.yml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: varlogs
__path__: /var/log/*.log
Com o LogQL, podemos realizar consultas poderosas. Para filtrar erros de um serviço específico:
{job="varlogs"} |= "ERROR" | json | line_format "{{.timestamp}} {{.message}}"
Para correlação com traces, extraímos o trace_id dos logs:
{job="api-service"} | regexp "trace_id=(?P<trace_id>[a-f0-9]+)" | line_format "{{.trace_id}}"
3. Tempo: Rastreamento Distribuído (Distributed Tracing)
Tempo é um backend de tracing distribuído que aceita spans no formato OpenTelemetry. Sua arquitetura armazena os dados brutos em object stores, indexando apenas os trace IDs e metadados essenciais, o que permite retenção de longo prazo com custo reduzido.
Para enviar spans de uma aplicação Go:
// main.go - configuração OpenTelemetry
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
"go.opentelemetry.io/otel/sdk/trace"
)
func initTracer() {
exporter, _ := otlptrace.New(
context.Background(),
otlptracegrpc.NewClient(
otlptracegrpc.WithEndpoint("tempo:4317"),
otlptracegrpc.WithInsecure(),
),
)
tp := trace.NewTracerProvider(trace.WithBatcher(exporter))
otel.SetTracerProvider(tp)
}
Para identificar gargalos, buscamos traces com duração elevada:
{ resource.service.name = "payment-service" } && { duration > 1s }
O Tempo permite visualizar a árvore de spans e identificar onde o tempo está sendo consumido, seja em chamadas HTTP, consultas a banco ou filas de mensageria.
4. Mimir: Métricas de Longa Retenção e Escalabilidade
Mimir é o sucessor do Cortex, projetado para armazenar métricas no formato Prometheus com alta disponibilidade e escalabilidade horizontal. Ele oferece compressão eficiente, downsampling automático e retenção configurável por períodos de meses ou anos.
Configuração básica de um tenant no Mimir:
# mimir-config.yml
multitenancy_enabled: true
blocks_storage:
backend: s3
s3:
bucket_name: mimir-metrics
endpoint: minio:9000
access_key_id: minio
secret_access_key: minio123
insecure: true
compactor:
retention: 90d
downsample:
enabled: true
retention: 30d
Uma consulta PromQL para monitorar SLOs:
# Taxa de erros 5xx nos últimos 5 minutos
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.01
Alertas baseados em SLOs podem ser configurados no Grafana ou no Alertmanager:
groups:
- name: slo-alerts
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
for: 10m
labels:
severity: critical
annotations:
summary: "Erro rate acima de 5% no serviço {{ $labels.service }}"
5. Correlação entre Logs, Traces e Métricas na Prática
A verdadeira potência da Grafana Stack está na correlação entre os três pilares. No Grafana, configuramos Derived Fields para extrair trace_ids dos logs e criar links diretos para o Tempo.
Passos para configurar:
- No datasource Loki, adicione Derived Fields apontando para o campo
trace_id - No datasource Tempo, configure o link de volta para logs com base no trace ID
- No datasource Mimir, adicione links para traces usando labels como
service_name
Estudo de caso: debug de um serviço de alto throughput
- Um alerta dispara no Grafana:
rate(http_requests_total{service="checkout"}[5m]) > 1000 - Clicamos no alerta e vemos o pico de métricas no Mimir
- No painel de métricas, clicamos em um trace específico que mostra latência alta
- No Tempo, visualizamos a árvore de spans e identificamos uma chamada lenta ao banco Redis
- Clicamos no span problemático e somos levados aos logs do Loki para aquele trace_id
- Nos logs, encontramos erros de timeout na conexão Redis
Todo o processo leva segundos, sem precisar alternar entre ferramentas diferentes.
6. Otimizações e Boas Práticas para Times Pequenos
Para times com recursos limitados, algumas estratégias ajudam a reduzir custos:
Retenção e compressão no Loki:
# Configuração de retenção no Loki
table_manager:
retention_deletes_enabled: true
retention_period: 30d
chunk_store_config:
max_look_back_period: 30d
storage_config:
boltdb_shipper:
active_index_directory: /data/loki/index
cache_location: /data/loki/cache
shared_store: s3
Multi-tenancy e RBAC:
# Configuração de tenants no Mimir
overrides:
tenant-a:
ingestion_rate: 10000
max_series_per_user: 50000
tenant-b:
ingestion_rate: 5000
max_series_per_user: 20000
Monitoramento da stack: Configure health checks para cada componente e alertas para alta cardinalidade de labels, que pode impactar performance e custos.
7. Conclusão e Próximos Passos
A Grafana Stack com Loki, Tempo e Mimir representa a evolução natural da observabilidade para sistemas modernos. A correlação nativa entre logs, traces e métricas elimina silos de informação e reduz drasticamente o tempo de diagnóstico de incidentes.
Para migração gradual, comece com Loki substituindo o Elasticsearch para logs, depois adicione Tempo para tracing e por último migre métricas do Prometheus standalone para Mimir. A integração com o Grafana existente facilita a transição.
A stack é particularmente valiosa para organizações que lidam com alto throughput e precisam de retenção de longo prazo sem explodir o orçamento de armazenamento. Com a comunidade ativa e documentação robusta, é uma escolha sólida para a lista final de temas em observabilidade.
Referências
- Documentação oficial do Loki — Guia completo de instalação, configuração e queries LogQL
- Documentação oficial do Tempo — Referência para configuração de tracing distribuído com OpenTelemetry
- Documentação oficial do Mimir — Guia de escalabilidade, multi-tenancy e configuração de métricas
- Grafana Labs - Blog oficial — Artigo técnico sobre correlação entre logs, traces e métricas
- OpenTelemetry Documentation — Padrão para instrumentação de aplicações e envio de spans para Tempo
- Grafana Play - Exemplos interativos — Ambiente de demonstração com dashboards pré-configurados da stack completa