Data Team MICGrafana Loki es el sistema open-source de agregación de logs para centralizar logs de servicios (Trino, Spark, Kafka, NiFi, Airflow, Ceph). Se integra con Grafana para búsqueda y visualización rápida. Los logs se envían vía Promtail (agente de recolección).
Acceso vía Grafana (recomendado)
<tu-url> → Data Sources → Loki
API REST de Loki (directo)
<tu-url>
Verificar estado
curl <tu-url>/ready
curl <tu-url>/loki/api/v1/status/buildinfo
| Componente | Rol | Ubicación |
|---|---|---|
| Distributor | Recibe logs vía push (Promtail) | <tu-url> |
| Ingester | Procesa y almacena logs en memoria | Interno |
| Querier | Lee logs de almacenamiento | API /loki/api/v1/query |
| Promtail | Agente recolector de logs | En cada nodo |
Ruta estándar
/etc/promtail/config.yml
Ver logs de Promtail
docker logs promtail --tail 50
# o
journalctl -u promtail -n 50
clients:
- url: <tu-url>/loki/api/v1/push
scrape_configs:
- job_name: trino
static_configs:
- targets:
- localhost
labels:
job: trino
__path__: /var/log/trino/*.log
| Label | Ejemplo | Descripción |
|---|---|---|
job |
trino |
Aplicación/servicio |
host |
trino-worker-01 |
Nombre del nodo |
environment |
production |
Entorno (prod, dev, staging) |
level |
error |
Nivel del log (si extractable) |
Logs de un job específico
{job="trino"}
Logs de múltiples jobs
{job=~"trino|spark"}
Filtrar por host
{job="kafka", host="kafka-broker-01"}
Logs que contienen palabra clave
{job="airflow"} |= "failed"
Logs que NO contienen palabra clave
{job="trino"} != "debug"
Coincidencia regex
{job="spark"} |~ "error.*timeout"
{job="kafka"}
|= "partition" # Contiene
!= "rebalance" # No contiene
|~ "lag.*[0-9]{5,}" # Regex: lag + 5+ dígitos
| Función | Ejemplo | Resultado |
|---|---|---|
rate() |
rate({job="trino"}[5m]) |
Líneas/segundo |
bytes_rate() |
bytes_rate({job="kafka"}[1m]) |
Bytes/segundo |
count_over_time() |
count_over_time({job="airflow"}[1h]) |
Líneas en 1 hora |
absent() |
absent(rate({job="ceph"}[5m])) |
Alerta si no hay logs |
Logs de una query fallida
{job="trino"} |= "FAILED" or "error"
Logs de queries lentas
{job="trino"} |~ "duration.*[0-9]{5,}"
Errores de memoria
{job="trino"} |= "OutOfMemory" or "memory exceeded"
Logs de jobs en ejecución
{job="spark"} |= "Running task" or "completed"
Fallos en executors
{job="spark"} |= "executor" and ("failed" or "lost")
Particiones y shuffle
{job="spark"} |~ "shuffle.*read.*[0-9]+ MB"
Consumer lag detectado
{job="kafka"} |= "consumer lag" or "lagging"
Rebalancing de particiones
{job="kafka"} |~ "Rebalancing|RebalanceInProgress"
Errores en brokers
{job="kafka"} |= "broker" and ("fatal" or "error")
Task failures
{job="airflow"} |= "Task failed" or "Retrying"
DAG schedule y runs
{job="airflow"} |~ "SchedulerJob|DagRun.*state.*"
Errores de conexión
{job="airflow"} |= "Connection refused" or "timeout"
Estado del cluster
{job="ceph"} |= "health" or "HEALTH_WARN"
OSDs down
{job="ceph"} |= "down" or "Out of quorum"
Datos no replicados
{job="ceph"} |= "undersized" or "degraded"
<tu-url>Crear alerta en Grafana si logs contienen error
count_over_time({job="trino"} |= "FAILED"[5m]) > 10
Alerta si no hay logs (servicio caído)
absent(rate({job="kafka"}[5m]))
Extraer duración de logs de Trino
{job="trino"} |~ "duration.*[0-9]+" | regexp "duration=(?P<duration>[0-9]+)"
Extraer status code de logs HTTP
{job="trino"} | regexp "status=(?P<status>\d+)"
curl '<tu-url>/loki/api/v1/query' \
--data-urlencode 'query={job="trino"}' \
--data-urlencode 'time=1678953600'
curl '<tu-url>/loki/api/v1/query_range' \
--data-urlencode 'query=rate({job="kafka"}[5m])' \
--data-urlencode 'start=1678867200' \
--data-urlencode 'end=1678953600' \
--data-urlencode 'step=300'
# Listar todos los label names
curl '<tu-url>/loki/api/v1/labels'
# Valores de un label específico
curl '<tu-url>/loki/api/v1/label/job/values'
| Convención | Ejemplo | Descripción |
|---|---|---|
| Job = servicio | job="trino" |
Nombre de la app/servicio |
| Host = nodo | host="trino-worker-01" |
Nodo donde corre |
| Environment | env="production" |
Entorno |
| Level | level="error" |
Severidad del log |
Usar filtros explícitos (rápido)
{job="trino", host="trino-worker-01"}
Evitar búsquedas sin job (muy lento)
# MALO
{} |= "error"
# BIEN
{job="spark"} |= "error"
Limitar rango de tiempo en dashboards
Last 1h, Last 6h en lugar de Last 7 daysLogs se guardan ~3 días por defecto. Para cambiar:
# En /etc/loki/loki-config.yml
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: s3
schema: v11
index:
prefix: index_
period: 24h
# Retención: 72 horas (3 días)
retention_deletes_enabled: true
retention_period: 72h
Recargar config
curl -X POST <tu-url>/loki/api/v1/reload
ps aux | grep promtail
# o
docker ps | grep promtail
docker logs promtail --tail 100
curl <tu-url>/ready
cat /etc/promtail/config.yml
Problema: Query sin filtro job=
# LENTO
{} |= "error"
# RÁPIDO
{job="trino"} |= "error"
Solución: Siempre incluir job= como primer filtro.
Ver uso de memoria:
curl <tu-url>/metrics | grep memory
Reducir max_chunk_age en config (flush más frecuente a almacenamiento).