Logstash - Méthode pour debugger les grokparsefailure


(Mika) #1

Bonjour à tous ! Je débute depuis plusieurs heures sur le parsing des log logstash.

C'est peut-être une question très anodine pour vous mais je cherche les "best practice" pour parser mes logs et surtout rechercher les erreurs.

J'ai tout fraichement réalisé un pattern grok et j'arrive à découper comme je le souhaite mais j'ai toujours un tag "grokparsefailure" . Dans ce cas je conclu que mon filter n'est pas "propre" ?
Quel est le moyen le plus pratique pour repérer les defaux de grokparsefailure ?

J'ai bien lu les doc et je me suis bien documenté. Étant donner que je n'ai peut être pas la logique d'un développeur je suis passé au travers de quelque chose.

C'est une question plutôt général donc dans un premier temps je ne demande pas de vérifier mon fichier de conf logstash.


(Mika) #2

Je viens de me rendre compte que le message n'étais pas affiché ! :expressionless:


(David Pilato) #3

Oui. Ca veut dire que les expressions régulières ne peuvent pas s'appliquer à tes lignes.

Quel est le moyen le plus pratique pour repérer les defaux de grokparsefailure ?

Dans Kibana il y a un Grok Debugger. Perso, j'aime beaucoup utiliser ça pour construire mon pattern Grok: http://grokconstructor.appspot.com/


(Mika) #4

Merci de ton retour,

C'est étrange parce que le découpage se fait correctement et comme je le souhaite. Avons nous la possibilité d’analyser à quel endroit le "parsing" ne s’effectue pas correctement ? Ou la meilleur des façons est de recommencer le fichier de conf petit à petit afin d'observer quand le grokparsefailure s’exécute ?

Oui j'ai justement utilisé Grokconstructor qui m'a été très utile pour monter dans un premier temps les regex.


(David Pilato) #5

C'est étrange parce que le découpage se fait correctement et comme je le souhaite.

Sans doute. SAUF pour la ligne en question qui est rejetée.

Avons nous la possibilité d’analyser à quel endroit le "parsing" ne s’effectue pas correctement ?

Je ne sais pas si il y a un debugger d'expressions régulières. Peut-être que @colinsurprenant sait ça...
En tout cas, déjà trouve la ligne qui ne fonctionne pas. Eventuellement partage là ici avec ton expression grok si tu n'y arrives pas.


(Mika) #6

Merci de ton retour.

J'ai effectué un nouveau logstash from scratch et je construis mon filtre petit à petit et je viens de me rendre compte que j'ai un grokparsefailure rien qu'en taguant déjà les log. Donc c'est déjà ma première démarche qui n'est pas bonne.

Exemple : J'ai un serveur où je récupère en syslog des log radius et dhcp. Je veux dans un premier temps les taguer pour ensuite les "parser" comme je veux.

 filter{
  if [type] == "server-syslog" {
    grok {
    match => { "message" => "radiusd" }
    add_tag => "radiusd"
    }
    grok {
    match => { "message" => "dhcpd" }
    add_tag => "dhcpd"
    }
  }
}

Le tag s'effectue bien sur chaque log mais j'ai un

[0] "_grokparsefailure",

Quelqu'un peut me guider afin d'avoir les bonnes pratiques sur la construction de mes filters logstash ?


(David Pilato) #7

N'utilise pas la citation pour formater du code mais le bouton </>. J'ai édité ton post.

Ici le parsing grok ne fonctionne pas car ta ligne ne contient pas que le texte dhcpd mais autre chose. Il faut donc que tu fasses une expression régulière qui corresponde à une ligne qui contient dhcpd.


(Mika) #9

D'accord et merci pour la correction de mon post.

Donc dans un premier temps j'effectue un parsing sur tout le message.

filter{
    if [type] == "syslog" {
         grok {
            match => { "message" => "%{SYSLOG5424PRI}%{SYSLOGTIMESTAMP}%{SPACE}%{WORD:Server_Name}%{SPACE}%{SYSLOGHOST:Service_Name}%{SYSLOG5424SD:ID_Service}%{NOTSPACE}%{GREEDYDATA:Message_du_log}" }
         }
         if [Service_Name] == "radiusd" {
             add_tag => "radiusd"
         }
         if [Service_Name] == "dhcpd" {
             add_tag => "dhcpd"
         }

 }
    } 

Est-ce que c'est la bonne manière de faire ?


(David Pilato) #10

Ca me semble une bonne idée.


(Mika) #11

Arf logstash n'aime pas cette configuration il ne se lance pas. Je vais continuer à chercher.


(Mika) #12

Je crois qu'effectuer des if dans grok n'est pas fonctionnel. Je dois trouver un moyen de séparer les logs en input je pense.


(David Pilato) #13

C'est pas dans grok c'est en dehors... Donc ça doit passer je pense.
Tu as quoi comme erreur ?


(Mika) #14

J'ai approfondi la doc et j'ai observé qu'il était possible d'utilisé grok dans l'input. ET de cette manière ça marche :blush: . Alors pareil je ne sais pas si c'est la manière la plus propre.

input {
   syslog {
      type => "syslog"
      port => 514
      grok_pattern => "<%{POSINT:priority}>%{SYSLOGTIMESTAMP:timestamp} %{WORD:Server_Name} %{SYSLOGHOST:Service_Name}%{SYSLOG5424SD:ID_Service}: %{GREEDYDATA:Message_du_log}"
  }
}

filter {
   if [Service_Name] == "radiusd" {
     grok {
        match => { "Service_Name" => "radiusd" }
        add_tag => "radiusd"
     }
   }
   if [Service_Name] == "dhcpd" {
     grok {
        match => { "Service_Name" => "dhcpd" }
        add_tag => "dhcpd"
     }
   }
}

En tout cas merci @dadoonet pour ton coup de main et de te prendre le temps. Ca me permet de progresser sur la solution.


(Mika) #15

J'ai trouvé un article sur le blog d'elasticsearch. Qui explique la bonne manière d'identifier et debugger les grokparsefailure.
Je le traduit et dépose ici. Cela pourra toujours servir :smiley:

Bien qu'il soit très important de savoir à quelle vitesse votre modèle grok correspond à une entrée de log, il est également essentiel de comprendre ce qui se passe quand ce n'est pas le cas. Les matchs réussis peuvent avoir des performances très différentes de ceux qui échouent.

Lorsque grok ne match pas à un événement, il ajoute une balise à l'événement. Par défaut, cette balise est _grokparsefailure.

Logstash vous permet ensuite d’acheminer ces events à un endroit où ils peuvent être comptés et examinés. Par exemple, vous pouvez écrire toutes les correspondances ayant échoué dans un fichier:

input { # ... }
filter {
  grok {
    match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} \[%{IPV4:ip};%{WORD:environment}\] %{LOGLEVEL:log_level} %{GREEDYDATA:message}" }
  }
}
output {
  if "_grokparsefailure" in [tags] {
    # write events that didn't match to a file
    file { "path" => "/tmp/grok_failures.txt" }
  } else {
     elasticsearch { }
  }
}

Et un joyeux Noël à tout le monde :slight_smile: :mrs_claus:


(Marc Antoine Jutras) #16

Personnellement j'ai un ELK en dévelopement et lorsque mes filtres en production ont des grokparsefailure, je met ces entrées dans un fichier log, je configure un filebeat en dev pour ce fichier et je déconstruit mon filtre en remplaçant la fin du filtre par "%{GREEDYDATA}". Je réimporte ensuite les entrées avec le filtre déconstruit jusqu'à ce que je trouve le morceau fautif.

Par exemple j'essaie mon filtre original:
%{TIMESTAMP_ISO8601:timestamp} \[%{IPV4:ip};%{WORD:environment}\] %{LOGLEVEL:log_level} %{GREEDYDATA:message}

Si ça ne passe pas j'essaie:
%{TIMESTAMP_ISO8601:timestamp} \[%{IPV4:ip};%{WORD:environment}\] %{GREEDYDATA:restant}

Puis:
%{TIMESTAMP_ISO8601:timestamp} \[%{IPV4:ip};%{GREEDYDATA:restant}

Etc.

Jusqu'à ce que le _grokparsefailure ne se produise plus. Puisque le "Greedydata" capture toujours le restant par défaut, lorsque ça passe c'est que la dernière portion enlevée ne fonctionnais pas.

Cela me permet souvent d'identifier la portion du filtre qui est fautive. :slightly_smiling_face:


(Mika) #17

C'est effectivement la même méthode que j'utilise. Lorsque j'ai un peu plus saisie le fonctionnement de Logstash.
Merci de ton retour !


(system) closed #18

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.