Installation et configuration de Logstash

Logstash? Qu’est-ce que c’est?

Logstash est un outil Java permettant d’interpréter les logs et d’exécuter plusieurs actions sur chaque message. On pourra ainsi extraire seulement certaines informations du message ou combiner plusieurs messages pour en faire un seul. Une fois les informations extraites, on peut écrire le nouveau message dans un fichier ou le fournir à un autre programme grâce à plusieurs connecteurs tels que AMQP ou elasticsearch. Toutes les infos sont disponibles ici.

Installation de logstash

Préliminaires

Puisque logstash est un outil Java, il faut commencer par installer l’environnement java. Rendez-vous ici, pour télécharger l’environnement correspondant à votre système. Une fois l’environnement téléchargé, installez le en suivant les instructions trouvées sur le site.

Téléchargement

Logstash est disponible en téléchargement gratuit sur le site officiel : http://logstash.net. Le téléchargement vous fournira un fichier “.jar” qui contient logstash mais également toutes les dépendances nécessaires. Il n’y a donc rien de plus à installer. Il suffit de copier le fichier où vous le souhaitez sur votre système.

Lancement

Logstash se lance grâce à la ligne de commande, il faut entrer la commande suivante “java -jar chemin_vers_logstash_monolitic.jar agent”. Pour ajouter des options il suffit d’ajouter en fin de ligne les options souhaitées. Les options disponibles pour l’agent sont :

  • -f ou –config chemin_vers_fichier : permet de spécifier dans quel fichier l’agent doit lire sa configuration
  • -v augmente la verbosité de l’agent
  • –log chemin_vers_fichier : définit le fichier de log à utiliser pour logstash

Ainsi, si le fichier logstash.jar se trouve à /opt/logstash/logstash.jar et que l’on a un fichier de configuration à /opt/logstash/logstash.conf, la commande ressemblera à

java -jar /opt/logstash/logstash.jar agent -f /opt/logstash/logstash.conf

Configuration de Logstash

Comme nous l’avons vu précédemment, l’outil logstash est configurable au travers d’un fichier. Logstash est écrit en grande partie en ruby, c’est pourquoi, vous le verrez plus loin, la configuration est très proche du langage ruby. Elle s’articule selon trois axes majeurs : “l’entrée (ou input)”, “les filtres (ou filter)” et “la sortie (ou output)”.

Avant de commencer à développer la configuration de logstash, nous allons voir la structure d’un événement. En effet, chaque ligne lue en entrée correspond à un événement sur lequel nous pourrons agir.

La structure des événements

Tous les événements logstash possèdent la même structure. C’est un objet JSON dans lequel nous trouverons toutes les informations :

  • @timestamp : date à laquelle logstash a lu le message
  • @tags : un tableau contenant des tags que l’on peut ajouter au message
  • @type : type du flux
  • @source : source d’où provient le message
  • @fields : tableau contenant des champs que l’on peut ajouter
  • @message : texte originale du message.

On pourra donc ajouter ou modifier chacun de ces champs pour avoir le message final le plus personnalisé possible.

Les entrées

Les entrées nous permettent de récupérer un flux avant de pouvoir le traiter. Logstash prend plusieurs types d’entrées différentes; un fichier, l’entrée standard, une file AMQP, ou encore les messages syslog. Nous verrons ici plus en détail comment régler une entrée sur un ou plusieurs fichiers.

Pour un fichier, logstash analysera chaque nouvelle ligne du fichier (il n’analyse pas ce qui était déjà dans le fichier avant qu’il soit lancé). Pour configurer ce type d’entrée, il faut ajouter au fichier logstash.conf :

input {
file {
path=> ["/var/log/fichier1", "/var/log/fichier2"]
}
}

Une fois le fichier déclaré, il faut attribuer un type à cette entrée. Le fichier de configuration devient alors :

input{
file {
path => ["/var/log/fichier1", "/var/log/fichier2"]
type => "mon_type_1"
}
}

Le type permettra d’identifier le flux dans la suite de la configuration, pour lui appliquer des filtres et lui associer une sortie.

On peut créer plusieurs entrées différentes pour distinguer plusieurs flux. Il suffit de créer un nouveau bloc “file” et de l’insérer à la suite du premier à l’intérieur du bloc “input”.

Les filtres

Les filtres vont nous permettre de modifier les événements. C’est ici qu’est faite la majeure partie du travail. Chaque filtre sera associé à un type de flux, type que l’on a indiqué dans la partie précédente. Il existe plusieurs type de filtres, les plus utiles sont les filtres :

  • grep : permet de ne choisir que certaines lignes
  • grok : permet d’extraire des informations du message original
  • mutate : permet de reformer l’événement

L’interprétation des filtres se fait dans l’ordre de leur déclaration dans le fichier.

Lors de l’utilisation de chaque filtre, on peut ajouter des tags ou des champs à l’événement à l’aide de l’option add_tag ou add_field.

Le filtre grep

Le filtre grep permet de ne garder que les événements qui correspondent à un pattern défini. Le pattern utilisé est une expression régulière.

Voici un exemple de déclaration d’un filtre grep :

filter {
grep {
type => "mon_type_1"
match => ["@message",".* Postit .*"]
}
}

Le filtre précédent permet de ne retenir que les événements dont le champ message contient le mot “Postit”. L’attribut “type” permet d’indiquer à quel type de flux le filtre doit s’appliquer, ici le type “mon_type_1″ défini dans la partie “input”. On peut ainsi diminuer le nombre de messages qui vont être traités par la suite, puisque tous les événements qui ne correspondent pas seront supprimés.

L’option “negate => true” permet de ne garder pour la suite que les messages qui ne correspondent pas au pattern entré. L’option “drop => false”, permet de conserver toutes les lignes pour la suite mais de n’appliquer les options add_tag et add_field (s’il y en a) qu’aux seules lignes qui correspondent au pattern.

Le filtre grok

Le filtre grok ressemble au filtre grep dans le sens où il se base sur les expressions régulières. Mais le filtre grok, lui, permet d’extraire de l’information et de la ranger dans le champs “fields” de l’événement. Logstash est fourni avec un grand nombre de patterns grok prédéfinis que vous pouvez trouver ici.

Voici un exemple de définition de filtre grok :

prenons comme message d’exemple “Mon message”

filter {
grok {
type => "mon_type_1"
pattern => "%{WORD} %{WORD}"
}
}

Le pattern créé nous permet donc de “scanner” tous les messages contenant deux mots, séparés par un espace. On pourra alors ajouter des tags ou des champs dans l’événement.

Mais jusqu’ici rien de différent par rapport au filtre grep, si ce n’est l’utilisation de patterns prédéfinis.

Grok permet d’enregistrer les informations dans certains champs. Ainsi en ajoutant la chaîne “:ma_variable” dans la définition d’un bloc du pattern on pourra enregistrer l’information.

Remplaçons le pattern précédent par celui-ci :

pattern => "%{WORD :premier_mot} %{WORD:second_mot}"

Maintenant lorsque le filtre va s’appliquer au message, il va créer un champ dans le tableau @fields avec pour nom premier_mot et pour valeur “Mon” ; ainsi qu’un deuxième champs avec pour nom second_mot et pour valeur “Message”.

On pourra ensuite récupérer ces informations dans de nouveaux filtres en entrant la chaîne suivante %{premier_mot}.

Le filtre mutate

Ce filtre permet de modifier la structure et le contenu du message. Il permet d’enlever, d’ajouter ou de modifier le contenu de chaque champs.

Les options principales sont :

  • Remove : permet d’enlever un champ.
  • Rename : permet de renommer un champ.
  • Replace : permet de modifier le contenu d’un champ.
  • Convert : permet de modifier le type d’un champ.

Nous allons voir ici comment récupérer et modifier le contenu du message pour inverser les deux mots sélectionnés précédemment.

filter {
mutate {
type => "mon_type_1"
replace => ["@message","%{second_mot} %{premier_mot}"]
}
}

On voit donc ici que l’on remplace le contenu du champ message et que celui-ci devient “message Mon”.

Les sorties

Le bloc sortie du fichier de configuration permet de configurer la façon dont logstash écrira les événements une fois les traitements terminés. Les sorties les plus utiles sont :

  • stdout : écrit sur la sortie standard (permet de débugger)
  • file : écrit dans un fichier
  • elasticsearch : passe le message à elasticsearch qui permettra une recherche efficace par la suite
  • amqp : permet de mettre le message dans une file amqp.

Nous verrons ici les deux premiers type. Pour déclarer une sortie il faut ajouter dans le fichier de configuration un bloc “output” comme nous l’avons fait pour les entrées et les filtres.

stdout

Pour la sortie “stdout” les options disponibles sont :

  • Debug : activer/désactiver le debug.
  • Type : pour n’afficher que les messages d’un type.
  • Tags : pour n’afficher que les messages ayant un ou plusieurs tag(s).

Un exemple :

output {
stdout {
type => "mon_type_1"
debug => true
}
}

Ici on affiche sur la sortie standard tous les messages de type “mon_type_1″ en activant le mode debug.

File

Pour écrire dans un fichier, on utilise la sortie file. Les options disponibles sont :

  • flush_interval : permet de régler au bout de combien de messages on écrit réellement dans le fichier. Par défaut la valeur est 2.
  • max_size : permet de régler la taille maximale du fichier dans lequel on écrit. Si le fichier dépasse la taille, une rotation à lieu. (Pas encore supporté au moment où nous écrivons ceci.)
  • message_format : permet de spécifier le format du message à écrire. Si rien n’est indiqué, l’intégralité du message est écrit.
  • Path : indique dans quel fichier écrire.

Un exemple :

output {
file {
path => "/var/log/mon_fichier"
type => "mon_type_1"
}
}

Ici on va écrire l’intégralité des événements de type “mon_type_1″ dans le fichier “/var/log/mon_fichier” et les écritures se feront tous les deux messages.

Voilà, nous avons les bases de la configuration de logstash, nous pouvons passer à un exemple complet.

 

Un exemple complet

Ici nous allons traiter l’intégralité de la configuration de logstash permettant de scanner un fichier, d’en extraire de l’information et d’écrire cette information dans un second fichier.

Nous prendrons ici comme exemple un fichier que nous remplirons au fur et à mesure, avec des lignes que nous rentrerons à la main. Nous intégrerons certaines lignes avec pour unique contenu “Login : un_login_au_hasard” ; le but sera d’écrire dans le second fichier la valeur du login entré sur ces lignes et aucune autre valeur.

De quoi avons-nous besoin

Nous avons donc besoin pour la configuration de logstash, d’une entrée de type “file”, d’un filtre de type “grep” pour ne sélectionner que les lignes désirées, d’un filtre de type “grok” pour extraire l’information, de filtres de type “mutate” pour modifier le message et d’une sortie de type “file” pour écrire dans le second fichier. On pourra aussi se servir de la sortie standard pour debugger notre programme.

 

Le fichier logstash.conf

Voici donc le fichier de configuration de logstash avec les commentaires utiles:

input {
#on définit l'entrée de type fichier.
file {
type => "login" #on attribue le type login aux lignes lues dans ce fichier.
path => [ "/var/tmp/test"]
}
}
filter {
#On commence par sélectionner les lignes contenant "Login :"
grep {
match => ["@message","^Login : .*"] #ici on ne prend que les lignes commençant par Login :
type => "login" #le filtre s'applique aux lignes du type login.
}
#On sélectione les infos que l'on veut sur la ligne
grok {
pattern =>"Login : %{WORD:login}" #ici on sélectionne le mot qui suit les deux points et le stocke dans le tableau associatif fields avec pour clé "login".
type => "login" #le filtre s'applique aux lignes du type login.
}
#On reforme le message avec les infos sélectionnées
mutate {
type => "login"
replace => ["@message","%{login}"] #On remplace le contenu du champ message en ne mettant que la valeur du login.
}
}
output {
#On garde la sortie standard pour le debug, on l'enlèvera lorsque le résultat nous conviendra
stdout {
debug => true
}
file {
type => "login"
path => "/var/tmp/sortie"
flush_interval => 0 #on écrira dans le fichier après chaque message
message_format => "%{@message}" #on veut simplement écrire le contenu du champ "message"
}
}

Ensuite pour tester notre configuration, il suffit de lancer la commande suivante dans un terminal :

java -jar /etc/logstash/logstash.jar agent -f /etc/logstash/logstash.conf

Nous allons ensuite utiliser un second terminal pour écrire dans le fichier “/var/tmp/test”.

Dans le second terminal nous exécutons la commande suivante :

echo test > /var/tmp/test

Rien ne se produit dans le terminal ou logstash est exécuté puisque la ligne ne correspond pas au pattern choisi. Puis nous insérons la ligne “Login : test” dans le fichier /var/tmp/test. Alors dans la fenêtre d’exécution de logstash on peut voir apparaître :

{
"@source" => "file://xxx.xxx.net//var/tmp/test",
"@type" => "login",
"@tags" => [],
"@fields" => {
"login" => [
[0] "test"
]
},
"@timestamp" => "2012-06-26T08:37:09.736000Z",
"@source_host" => "xxx.xxx..net",
"@source_path" => "//var/tmp/test",
"@message" => "test"
}

C’est l’intégralité de l’évènement logtash au format json. C’est normal que nous ayons l’intégralité de l’évènement puisque dans la sortie stdout nous n’avons pas reformatter l’évènement.

Dans le fichier “/var/tmp/sortie” on a une seule ligne qui contient le text “test”. En effet nous avons indiqué que nous ne voulions que le contenu du champ message dans le fichier de sortie grâce à la ligne

message_format => "%{@message}"

L’utilisation de logstash n’a maintenant plus aucun secret pour vous.

Une réflexion sur “ Installation et configuration de Logstash ”

  1. Excellent article. Peut-être pourriez vous ajouter comment lier une appli existante utilisant log4j avec Logstash. C’est très simple et super pratique !nn1

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *