Loki + Grafana: logs centralizados na VPS
Grafana Loki é o "Prometheus para logs" — armazena apenas os metadados (labels) dos logs com índices, mantendo o texto bruto comprimido em storage. É 10× mais econômico que o Elasticsearch para a maioria dos casos de uso. Integrado ao Grafana que você já tem, centraliza logs de todos os containers e serviços em um único painel.
Instalar Loki com Docker Compose
Stack completa com Loki, Promtail e Grafana:
yaml
# docker-compose.yml
services:
loki:
image: grafana/loki:latest
restart: always
ports:
- "127.0.0.1:3100:3100"
command: -config.file=/etc/loki/local-config.yaml
volumes:
- loki_data:/loki
- ./loki-config.yaml:/etc/loki/local-config.yaml
promtail:
image: grafana/promtail:latest
restart: always
volumes:
- /var/log:/var/log:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- ./promtail-config.yaml:/etc/promtail/config.yaml
command: -config.file=/etc/promtail/config.yaml
grafana:
image: grafana/grafana:latest
restart: always
ports:
- "127.0.0.1:3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
volumes:
- grafana_data:/var/lib/grafana
volumes:
loki_data:
grafana_data:Configurar Promtail para coletar logs
promtail-config.yaml para ler logs do Docker e do sistema:
yaml
# promtail-config.yaml
server:
http_listen_port: 9080
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
# Logs de containers Docker:
- job_name: docker
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: ['__meta_docker_container_name']
target_label: container
- source_labels: ['__meta_docker_container_log_stream']
target_label: stream
- source_labels: ['__meta_docker_compose_service']
target_label: service
# Logs do Nginx:
- job_name: nginx
static_configs:
- targets: [localhost]
labels:
job: nginx
__path__: /var/log/nginx/*.log
# Logs do sistema (auth, syslog):
- job_name: system
static_configs:
- targets: [localhost]
labels:
job: system
__path__: /var/log/{auth,syslog}.logQueries LogQL no Grafana
Pesquisar e filtrar logs com a linguagem LogQL:
bash
# LogQL — sintaxe similar ao PromQL
# Todos os logs de um container:
{container="minha-api-app-1"}
# Filtrar por texto (grep):
{container="minha-api-app-1"} |= "ERROR"
# Excluir linha:
{job="nginx"} != "health"
# Parsear JSON estruturado e filtrar por campo:
{container="minha-api"} | json | level="error"
# Parsear log do Nginx (logfmt):
{job="nginx"} | logfmt | status >= 500
# Contar erros por minuto (métrica a partir de log):
rate({container="minha-api"} |= "ERROR" [1m])
# Top 10 IPs com mais erros 500:
topk(10,
sum by (remote_addr) (
rate({job="nginx"} | logfmt | status=~"5.." [5m])
)
)
# No Grafana — Explore → Loki → inserir query LogQL
# Ou criar dashboard com painéis de logConfigurar alertas baseados em logs
Alertar quando padrão de erro aparece nos logs:
yaml
# No Grafana — Alerting → Alert Rules → New rule
# Usar Loki como data source
# Exemplo: alertar quando > 10 erros 500 em 5 min:
# Query:
sum(rate({job="nginx"} | logfmt | status=~"5.." [5m])) > 0.033
# Ou via arquivo de regras do Loki (ruler):
# loki-config.yaml — adicionar:
ruler:
storage:
type: local
local:
directory: /loki/rules
rule_path: /loki/rules
alertmanager_url: http://alertmanager:9093
# /loki/rules/default/rules.yaml:
groups:
- name: api-errors
rules:
- alert: HighErrorRate
expr: |
sum(rate({container="minha-api"} |= "ERROR" [5m])) > 1
for: 2m
labels:
severity: warning
annotations:
summary: "Taxa de erros alta na API"Dica
Loki precisa de acesso ao socket Docker (/var/run/docker.sock) no Promtail para descoberta automática de containers. Adicione o volume no compose do Promtail.
Enviar logs da aplicação diretamente ao Loki
Integrar Node.js com Loki via Pino ou Winston:
typescript
// npm install pino pino-loki
import pino from 'pino'
const logger = pino({
transport: {
targets: [
// Console (desenvolvimento):
{ target: 'pino-pretty', level: 'debug', options: {} },
// Loki (produção):
{
target: 'pino-loki',
level: 'info',
options: {
host: 'http://localhost:3100',
labels: {
app: 'minha-api',
env: process.env.NODE_ENV,
},
// Enriquecer com campos do log como labels:
propsToLabels: ['level', 'service'],
// Intervalo de envio em batch (ms):
interval: 5,
},
},
],
},
})
// Usar o logger na aplicação:
logger.info({ userId: '123', route: '/api/pedidos' }, 'Pedido criado')
logger.error({ err: error, userId: '123' }, 'Falha ao processar pedido')
// Os logs aparecem automaticamente no Grafana Explore → Loki$ runstack deploy --plan starter
Não quer configurar manualmente?
Não quer configurar manualmente? Implante o VPS em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.