Consulter les logs¶
Loki est le système de stockage des logs. C'est un système d'agrégation de logs horizontalement scalable, hautement disponible et multi-tenant, inspiré de Prometheus et dirigé par Grafana Labs.
Loki est consitué de plusieurs composants dont les distributors et ingesters (ingèrent et stockent les logs dans S3) et les queriers (interrogent S3 et transmettent le résultat à l'outil qui emet la requête, généralement Grafana).
LogQL¶
Pour interroger les logs, Loki utilise logQL : Log Query Language.
Consultez la documentation LogQL pour plus de détails.
LogQL peut être utilisé dans l'onglet Explore de Grafana avec la datasource Loki
.
Il est possible de choisir d'afficher les logs ou le nombre de logs.
Logs¶
Sélecteur de flux de logs¶
Nous choisissons un sélecteur de flux de log (logs stream selector). Le sélecteur de flux est composé d'une ou plusieurs paires clé-valeur, où chaque clé est un label de log et la valeur est la valeur de ce label.
Dans le sélecteur de flux, vous pouvez utiliser différents opérateurs :
=
(est exactement égal)!=
(n'est pas égal)=~
(correspond à la regex)!~
(ne correspond pas à la regex)
Exemple :
{app="eventrouter",namespace="caascad-eventrouter"}
Cet exemple récupère toutes les lignes de log avec les labels app="eventrouter"
et namespace="caascad-eventrouter"
.
Pipeline de log¶
Nous pouvons également filtrer le contenu des expressions.
L'expression de recherche peut être juste du texte ou une regex.
Dans l'expression de recherche, vous pouvez utiliser différents opérateurs :
|=
: La ligne de log contient une chaîne de caractères.!=
: La ligne de log ne contient pas de chaîne de caractères.|~
: La ligne de log correspond à une expression régulière.!~
: La ligne de log ne correspond pas à une expression régulière.
Example:
{app="eventrouter",namespace="caascad-eventrouter"} |= "UPDATED"
Cet exemple récupère toutes les lignes de log :
- avec les labels
app="eventrouter"
etnamespace="caascad-eventrouter"
- contenant le mot
UPDATED
Note
Dans Grafana, le nombre de lignes de logs maximum obtenu par une seule requête est de 1000. Pour obtenir des logs plus anciens, vous devez modifier la période de recherche de votre requête à une date antérieure.
Parseur log¶
Nous pouvons parser les logs pour extraire les labels lors de la requête.
Les parseurs disponibles sont:
- json
- logfmt
- regexp
- pattern
Exemple¶
Sans parseur:
{app="promtail"}
Avec le parseur logfmt
:
{app="promtail"} | logfmt
Nous pouvons voir que nous avons des labels en plus comme level
, msg
...
Quand il y'a un problème pendant le parsing, un label __error__=JSONParserErr
est rajouté:
{app="promtail"} | json
Avec le parseur pattern
:
{container="nginx"} | pattern "<_> - - [<_>] <code> \"<method> <uri> <_>"
Nous pouvons voir que les labels code
, method
et uri
sont bien présents.
Astuce
Pour utiliser ce parseur, vous pouvez :
- obtenir une ligne de log, dans l'exemple :
172.16.0.225 - - [09/Sep/2022:17:25:37 +0000] 204 "POST /api/prom/push HTTP/1.1" 0 "-" "promtail/2.2.1" "-"
- remplacer les informations voulues par le nom du label mis entre
< >
:172.16.0.225 - - [09/Sep/2022:17:25:37 +0000] <code> "<method> <uri> HTTP/1.1" 0 "-" "promtail/2.2.1" "-"
-
remplacer les informations non voules par un
_
mis entre< >
:<_> - - [<_>] <code> \"<method> <uri> HTTP/1.1" <_>
Attention : les
"
dans les lignes de logs doivent être échappés.
Filtre log¶
Nous pouvons filtrer sur les labels extraits pendant le parsing.
Exemple¶
{app="promtail"} | logfmt | level="error"
{app="promtail"} | logfmt | level="info"
Plusieurs opérations sont possibles :
- avec des strings:
=,!=,=~,!~
- avec des nombres, des durées, des bytes:
=,!=,<,>,<=,>=
Réécriture de logs¶
Nous pouvons réécrire les logs en utilisant leurs labels.
Exemples:¶
{app="promtail"} | logfmt | line_format "pod={{.pod}} msg={{.msg}}"
{app="promtail"} | logfmt | line_format "level={{.level | ToUpper}} msg={{.msg}}"
Les fonctions qui sont disponibles sont ici.
Réécriture de labels¶
Nous pouvons réécrire les labels des logs.
Exemple:¶
{app="promtail"} | logfmt | label_format pod="{{.namespace}}/{{.pod}}/{{.container}}"
Le label pod
a été réécrit avec les labels namespace
, pod
et container
.
Nous pouvons utiliser les mêmes fonctions que pour la réécriture de logs.
Graphe¶
Nous pouvons utiliser les labels extraits comme ensemble de valeurs au lieu de lignes de logs.
Exemple :¶
{container="blackbox-exporter"} | logfmt
avg(avg_over_time({container="blackbox-exporter"} | logfmt | unwrap duration_seconds | __error__="" [1h])) by (module, target)
Nous utilisons le label duration_seconds
et nous faisons une moyenne sur une période de 1 heure, en agrégeant sur les labels module
et target
.
Nous spécifions __error __ =" "
pour les lignes de logs qui n'ont pas le label duration_seconds
.
Par défaut, le label duration_seconds
est converti en float (64 bits).
Plusieurs fonctions sont possibles, comme avg_over_time
, max_over_time
, min_over_time
. Voir la documentation officielle pour plus de détails.
Nombre d'entrées¶
Nous pouvons compter les entrées par flux.
Les principales fonctions pouvant être appliquées sont :
rate
: calcule le nombre d'entrées par secondecount_over_time
: compte les entrées pour chaque flux de log dans la plage donnéesum
: calcule la somme sur les labelsmin
: sélectionne le minimum sur les labelsmax
: sélectionne le maximum sur les labelsavg
: calcule la moyenne sur les labelsstddev
: calcule l'écart type de la population sur les labelsstdvar
: calcule la variance de la population sur les labelscount
: compter le nombre d'éléments dans le vecteurbottomk
: sélectionne les k plus petits éléments par valeur d'échantillontopk
: sélectionne les k plus grand éléments par valeur d'échantillon
Exemple:
count_over_time({app="eventrouter",namespace="caascad-eventrouter"}[5m])
Cet exemple compte toutes les lignes de log des cinq dernières minutes portant les labels app="eventrouter"
et namespace="caascad-eventrouter"
.