RousselTMLEARNING

Observabilité

LogQL (1/2) : requêter les logs (sélecteurs, filtres et parsers)

Apprendre LogQL : sélecteurs de flux, filtres de ligne, parsers json/logfmt/pattern/regexp, filtres de labels, formatage de lignes et bonnes pratiques de performance.

1. Le sélecteur de flux #

Obligatoire et toujours le plus précis possible.

Matchers #

Pipeline LogQL
Plus le sélecteur est précis, moins Loki lit de données.
{app="api"}                                  # égalité
{app!="api"}                                 # différent
{app=~"api|web"}                             # expression régulière
{namespace="prod", app=~"checkout-.*"}       # plusieurs labels
{app="api", env!~"dev|test"}                 # exclusion
Erreur Courante : Un sélecteur doit contenir au moins un matcher non vide : {app=~".*"} est refusé car trop coûteux.

2. Filtrer les lignes #

Du plus rapide au plus coûteux.

Filtres de ligne #

{app="api"} |= "error"                   # contient
{app="api"} != "healthcheck"                 # ne contient pas
{app="api"} |~ "timeout|refused"             # regex
{app="api"} !~ "GET /static/.*"              # ne correspond pas à la regex
{app="api"} |= "error" != "healthcheck" |~ "user=\\d+"   # enchaînement
{app="api"} |= ip("10.0.0.0/8")              # filtre sur adresse IP
Bonne Pratique : Mettez les filtres |= et != avant les parsers : ils sont bien plus rapides que parser puis filtrer.

3. Parser les lignes #

Extraire des champs.

json, logfmt, pattern et regexp #

# JSON : {"level":"error","method":"GET","path":"/api","status":502,"duration_ms":340}
{app="api"} | json
{app="api"} | json level="level", http_status="status"      # extraire en renommant
{app="api"} | json | status >= 500 and duration_ms > 300

# logfmt : level=error method=GET path=/api status=502
{app="api"} | logfmt | level="error"

# pattern : lignes d'accès simples (très rapide)
{app="nginx"} | pattern `<ip> - - [<_>] "<method> <uri> <_>" <status> <size>` | status >= 500

# regexp : captures nommées
{app="app"} | regexp `user=(?P<user>\w+) action=(?P<action>\w+)`

Filtres sur labels extraits #

{app="api"} | json | level="error"
{app="api"} | json | status=~"5.."
{app="api"} | json | duration_ms > 250 and method="POST"
{app="api"} | json | __error__=""                    # ignorer les lignes non parsables
{app="api"} | logfmt | duration > 1s                # durée typée (1s, 500ms)
{app="api"} | json | bytes > 5MB                    # taille typée

4. Mettre en forme #

line_format, label_format et drop/keep.

Reformater la sortie #

{app="api"} | json | line_format "{{.method}} {{.path}} -> {{.status}} ({{.duration_ms}} ms)"
{app="api"} | json | label_format route=path, ms=duration_ms
{app="api"} | json | drop user_agent, request_id
{app="api"} | json | keep level, status, path
{app="api"} | json | line_format `{{ .level | upper }} {{ .msg | trunc 80 }}`

Bonnes pratiques de performance #

  • Réduire la plage de temps et le nombre de flux avant d'affiner.
  • Préférer pattern (ou logfmt) à regexp : ils sont nettement plus rapides.
  • Utiliser la structured metadata pour les identifiants et les filtrer sans parser.
  • Limiter l'affichage avec limit (Explore) ou --limit (logcli).
logcli query '{app="api"} |= "error" | json | status>=500' --since=30m --limit=50 --output=jsonl
logcli query '{app="api"}' --since=1h --stats          # volumes lus : octets, lignes, flux

Articles liés

Grafana Loki : le système de logs inspiré de Prometheus

Découvrir Grafana Loki : philosophie d'indexation par labels, architecture (distributor, ingester, querier, c…

Installer Grafana Loki (Docker Compose, binaire et Helm)

Installer et valider Grafana Loki : configuration minimale, Docker Compose avec Grafana et Alloy, installatio…

Collecter des logs vers Loki : Alloy, Promtail, Docker et OpenTelemetry

Envoyer des logs vers Loki : Grafana Alloy, Promtail, driver Docker, OTLP, bons labels, parsing et enrichisse…

Pour aller plus loin