Créer un conteneur Docker pour traiter vos logs Magento 2 avec Logstash
Objectif
Faire remonter l'ensemble des logs Magento 2 vers un ELK en utilisant Logstash.
Pré-requis
Dans cet article, nous verrons uniquement la mise en place d'un container Logstash sous Docker pour envoyer vos logs à un serveur Elasticsearch.
Si vous souhaitez mettre en place un serveur ELK, je vous invite à prendre connaissance de la playlist ELK de Xavki, lien vers la playlist.
Tutoriel
Création du projet
Arborescence
Commençons par créer un dossier dans lequel nous allons travailler :
mkdir m2-logstash && cd m2-logstash
Dans ce dossier, nous allons créer les dossiers pour les volumes persistants de notre conteneur Docker :
mkdir -p conf/logstash
Fichier de configuration : logstash.yml
Dans le dossier conf/logstash
, nous allons créer le fichier logstash.yml
qui contiendra :
http.host: "0.0.0.0"
xpack.monitoring.enabled: false
xpack.monitoring.elasticsearch.hosts: [ "http://url-elasticsearch:9200" ]
Avant d'enregistrer et de fermer le fichier, n'oubliez pas de modifier url-elasticsearch
vers l'URL de votre serveur Elasticsearch.
Si vous souhaitez plus d'informations sur la configuration, je vous invite à consulter la documentation, lien vers la documentation.
Pour éviter les erreurs dans les logs de Logstash, j'ai ajouté les 2 lignes concernant xpack
.
Fichier : logstash.Dockerfile
Pour lancer le conteneur de Logstash, nous avons besoin de 2 lignes pour le moment.
FROM logstash:7.9.3
COPY ./conf/logstash/logstash.yml /usr/share/logstash/config/logstash.yml
Veillez bien à utiliser la version de Logstash compatible avec votre serveur Elasticsearch.
Fichier : docker-compose.yml
A la racine de notre projet (dossier m2-logstash
), nous allons créer un fichier docker-compose.yml
contenant :
version: '3'
services:
logstash:
build:
context: .
dockerfile: logstash.Dockerfile
networks:
- myNetwork
networks:
myNetwork:
driver: bridge
Configuration de Logstash
Magento 2 génère ses logs dans le dossier var/log
, nous allons donc configurer Logstash pour qu'il consulte en permanence ce dossier.
Pour cela, il faut que les logs de Magento soit accessible par la machine hôte. Dans mon cas, je lance Magento 2 avec Docker, lien vers le tutoriel.
Mise en place du volume persistant
Une fois que les fichiers de logs sont accessibles sur la machine hôte, il faut mettre en place un volume persistant à notre conteneur logstash
avec les 2 lignes ci-dessous :
volumes:
- ./racine_de_magento/var/log:/var/log/magento
Les 2 lignes sont à ajouter au fichier docker-compose.yml
, le résultat est le suivant :
version: '3'
services:
logstash:
build:
context: .
dockerfile: logstash.Dockerfile
volumes:
- ./racine_de_magento/var/log:/var/log/magento
networks:
- myNetwork
networks:
myNetwork:
driver: bridge
N'oubliez pas de remplacer racine_de_magento
.
Fichier de traitement des logs
Concentrons-nous maintenant sur le fichier de configuration pour le traitement des logs Magento 2.
Le fichier ci-dessous est composé de 3 parties :
- input
- filter
- output
Vous retrouverez quelques explications sur chaque paramètre utilisé à la fin du tutoriel.
Le contenu ci-dessous doit être insérer dans un fichier nommé magento2.conf
dans le dossier conf/logstash
.
input {
file {
type => "magento-log"
path => "/var/log/magento/*.log"
exclude => ["*.gz"]
codec => multiline {
pattern => "^\[%{TIMESTAMP_ISO8601}\]"
negate => true
what => "previous"
}
}
}
filter {
if [type] == "magento-log" {
grok {
match => {
"message" => "\[%{TIMESTAMP_ISO8601:date}\] %{WORD:word}.%{WORD:level}: %{GREEDYDATA:content} \[\]"
}
}
date {
match => ["date", "yyyy-MM-dd HH:mm:ss"]
timezone => "Europe/Paris"
}
mutate {
copy => { "[@timestamp]" => "date" }
add_tag => [ "%{level}" ]
}
if "_grokparsefailure" in [tags] {
mutate {
remove_field => [ "message" ]
}
}
}
}
output {
if [type] == "magento-log" {
elasticsearch {
hosts => ["url-elasticsearch:9200"]
index => "magento2-%{+YYYY.MM.dd}"
}
if "_grokparsefailure" in [tags] {
elasticsearch {
hosts => ["url-elasticsearch:9200"]
index => "magento2_grokparsefailure-%{+YYYY.MM.dd}"
}
}
}
}
Avant d'enregistrer et de fermer le fichier, n'oubliez pas de modifier url-elasticsearch
vers l'URL de votre serveur Elasticsearch.
Une fois le fichier enregistré, nous allons copier ce ficiher dans le conteneur en modifiant le fichier logstatsh.Dockerfile
. Ajouter à la fin du fichier la directive :
COPY ./conf/logstash/magento2.conf /usr/share/logstash/pipeline/magento2.conf
Enregister et fermer le fichier. Puis lancer la commande :
docker-compose build && docker-compose up -d
Résultat
Pour contrôler que les données remontent correctement, je vous invite à activer les crons de votre boutique en ligne puis de lancer la commande docker logs m2-logstash_logstash_1 -f
où de d'ouvrir Kibana dans votre navigateur.
Dans mon cas, le conteneur Logstash est : m2-logstash_logstash_1
.
Tutoriel publié le 23/11/2020.
Les paramètres utilisés
Bloc : Input
Pour traiter les fichiers, nous utilisons le plugin file
de Logstash, lien vers la documentation.
Voici un résumé des propriétés que j'ai utilisées pour la partie :
type
: Ce paramètre sera présent dans Elasticsearch et nous servira pour poser quelques conditions dans le fichier de configuration.path
: Indique à Logstash le ou les fichiers à traiterexclude
: Exclude est un tableau qui permet d'exclure le traitement de certains fichiers, dans mon cas, je refuse de traiter les fichiers *.gzcodec
: Permet de traiter plusieurs lignes de logs en se basant sur un pattern, lien vers la documentation
Bloc : Filter
Le bloc filter
permet de traiter le contenu de chaque fichier. J'ai ajouté la condition if [type] == "magento-log" {}
pour sécuriser le traitement des logs par Logstash. On peut également personnaliser le traitement des logs.
Le découpage des lignes de chaque fichier est traité par le plugin grok
, lien vers la documentation. C'est un plugin assez puissant basé sur les expressions régulières. Dans le cas où grok
ne parviendrait pas à parser les logs, il ajoute le tag _grokparsefailure
.
Le plugin date
permet de faire correspondre le format de date du fichier pour un traitement. Dans notre cas, je fais correspondre la date des fichiers de log Magento 2 pour le copier dans le champ [@timestamp]
. Ceci est très important car lors de l'analyse des logs, il n'y aura pas d'erreur de date et d'heure, lien vers la documentation. J'en profite également pour renseigner le fuseau horaire.
Le plugin mutate
me sert pour remplacer le contenu du champ date
dans le champ [@timestamp]
et aussi pour ajouter le tag level
qui correspond au niveau de gravité du log, lien vers la documentation.
Nous finissons par la condition if "_grokparsefailure" in [tags] {}
qui va supprimer le champ message
lorsque le plugin grok
n'aura pas rencontré d'erreur. Ceci permet également de réduire le volume de données stockés par le serveur Elasticsearch.
Bloc : Output
Comme pour le bloc filter
, j'ai ajouté une condition autour des 2 paramètres dans le but de sécuriser l'envoi des données sur le serveur Elasticsearch. Il existe plusieurs plugins de sortie pour Logstash, voir la liste. Dans mon cas, j'ai utilisé le plugin Elasticsearch
, lien vers la documentation.
Très simplement, nous envoyons les données au serveur Elasticsearch de notre choix en précisant le nom de l'index magento2-%{+YYYY.MM.dd}
. L'index est horodaté pour éviter un poids important.
Nous utilisons à nouveau la condition if "_grokparsefailure" in [tags] {}
pour également envoyer, dans un autre index, les erreurs rencontrées par grok
lors du traitement des journaux.