· Tutorial · 15 min read
Logstash, ElasticSearch, Kibana - S01E02 - Analyse orientée business de vos logs applicatifs
Nous allons voir comment mettre à profit nos logs applicatifs afin de faire de l’analyse orientée "business" grâce à Logstash, ElasticSearch et Kibana.
Les logs d’une application sont utilisés le plus souvent afin d’analyser un incident en production.
Ces lignes parfois trop complexes, même pour un développeur, sont générées par Go voir Tera toutes les heures, suivant votre infrastructure.
Elles sont trop souvent sous-exploitées au regard du nombre d’informations précieuses disponibles.
Nous allons voir comment mettre à profit nos logs applicatifs afin de faire de l’analyse orientée “business” grâce à Logstash, ElasticSearch et Kibana.
Dans ce billet de blog, nous serons à la tête d’un site fictif de vente en ligne, et essaierons de répondre aux questions suivantes :
- Quel est le ratio recherches / ventes ?
- Quels sont les critères de recherches les plus utilisés ?
- Quels sont les produits les plus consultés ?
- Quels sont les produits les plus vendus (iPhone 5S, Galaxy S4) ?
- Quels sont les modèles les plus vendus (iPod Shuffle Bleu, iPhone 5S 64 Go Argent) ?
- Qui sont mes plus fidèles clients ? Où sont-ils (géo)localisés ?
- Quelle est la proportion homme / femme de mes acheteurs ?
- Où nous situons-nous par rapport à nos objectifs de ventes ?
- etc…
Format des logs
Ce paragraphe vous présente le format des logs que nous allons exploiter.
Vous pouvez utiliser l’application log-generator disponible sur Github afin de générer des logs facilement.
Voici un exemple permettant de générer 10 logs, puis 100 logs toutes les secondes sur 2 threads :
Voici quelques exemples de recherches/visites d’un produit :
Dans l’exemple ci-dessus, les logs représentent respectivement :
- une requête (id 1) de recherche sur la catégorie “Portable”, venant de l’ip 92.90.16.222
- une requête (id 12) de recherche sur la catégorie “Mobile” et la marque “Samsung”, venant de l’ip 90.33.93.13
- une requête (id 35) de recherche sur la catégorie “Portable” et la marque “Apple”, avec un écran 11 pouces et un disque 128 Go, venant de l’ip 82.121.185.168
- une visite (id 41) du produit “iPhone 5C”, modèle blanc avec une capacité de 16Go, au prix de 599 €, venant de l’ip 157.55.34.94
Voici un exemple de log d’une vente :
Ici, le log nous informe que notre cliente a acheté une Tablette Nexus 10 de capacité 16Go au prix de 399€.
Logstash
Logstash est un pipe permettant de collecter, parser, et stocker des logs à l’aide d’entrées, de filtres et de sorties (input, filter, output).
La phase de parsing permet d’ajouter de la sémantique à notre événement, en ajoutant, modifiant ou supprimant des champs, des tags, des types, etc…
Cet article utilise la version 1.2.1 de Logstash, qui comporte entre autres :
- 37 types d’entrée
- 39 filtres
- 51 types de sortie
De quoi vous brancher à pas mal de systèmes au sein de votre SI…
Le JAR est disponible à cette adresse : https://download.elasticsearch.org/logstash/logstash/logstash-1.2.1-flatjar.jar
Configuration minimale
Créez un fichier de configuration minimaliste nommé “logstash-logback.conf” :
Lancez Logstash avec cette configuration :
Copiez/collez dans l’entrée standard une ligne de log :
Logstash affichera alors sa représentation au moment de la réception :
Le champ message contient la ligne de log brute, @timestamp contient la date de l’événement.
Un œil averti aura remarqué que le champ @timestamp n’est pas le même que la ligne originale.
Logstash a en effet pris la date d’insertion ne sachant pas quel “bout” de log utiliser.
Le premier travail va consister à parser le log à l’aide d’une regex…
Ajout de sémantique avec le filtre Grok
Le filtre grok va nous permettre de parser les lignes de logs et leur donner de la sémantique.
Logstash vient avec plus d’une centaine d’expressions régulières prédéfinies (disponibles ici : https://github.com/logstash/logstash/tree/master/patterns).
Par exemple, le pattern “COMBINEDAPACHELOG
” du fichier grok-patterns permet de matcher les lignes de logs d’un serveur Apache.
Vous pouvez utiliser 2 syntaxes :
%{SYNTAX:SEMANTIC} ou
%{SYNTAX:SEMANTIC:TYPE}
(?<field_name>the pattern here)
La première syntaxe réutilise un pattern Logstash (ex: MONTHDAY
, NOTSPACE
, LOGLEVEL
, …), SEMANTIC
étant le nom du champ à mapper.
Vous pouvez aussi préciser le type du champ (integer, float, String) via le paramètre TYPE
.
La deuxième syntaxe vous permet de définir un pattern customisé avec ou sans l’aide de plusieurs patterns “logstash”.
Voici une configuration permettant de parser nos logs :
Si vous relancez Logstash, et copiez/collez la première ligne, vous devriez obtenir une sortie similaire :
On remarque que Logstash a parsé les champs log_date, thread, log_level, classname et msg.
Lorsque Grok échoue, il ajoute le tag “_grokparsefailure” à votre évènement :
Dossier de patterns
Plutôt que d’utiliser une longue expression régulière dans votre configuration, définissez un fichier contenant vos patterns personnalisés.
Créez un dossier “patterns” dans votre répertoire courant.
Créez un fichier “logback” dans le dossier “patterns” contenant :
Indiquez ensuite à Grok le dossier contenant vos fichiers de patterns via l’attribut “patterns_dir”.
La configuration Losgstash devient :
Le bon @Timestamp avec le filtre date
Le filtre date est l’un des filtre les plus importants. Il permet en effet de parser une date et de l’utiliser pour le champ @timestamp.
Cette étape est cruciale (souvenez-vous du panel “timepicker” dans Kibana…).
Vous pouvez spécifier les 4 formats de date suivants :
- “ISO8601” : timestamp ISO8601 (ex: 2011-04-19T03:44:01.103Z)
- “UNIX” : temps écoulé depuis epoch en secondes
- “UNIX_MS” : temps écoulé depuis epoch en millisecondes
- “TAI64N”
- un pattern au format org.joda.time.format.DateTimeFormat
Dans notre configuration, nous allons utiliser un pattern au format Joda :
Le champ @timestamp utilise enfin la date de notre log :
Vous pouvez le vérifier en copiant/collant plusieurs fois la même ligne de log, Logstash devrait utiliser le même timestamp.
Parsing d’un champ avec le filtre kv
Le filtre kv s’avère très utile lorsque vous voulez parser un champ de type foo=bar comme par exemple une requête HTTP.
Ajoutez le filtre kv pour notre example :
Logstash parse maintenant notre ligne de vente et ajoute automatiquement les champs category, brand, name, model, color, options et price :
Conditions
Logstash permet d’utiliser des conditions via la syntaxe :
Les expressions peuvent contenir :
- une égalité, comparaison :
== != < > <= >=
- un pattern :
=~ !~
- une inclusion :
in not in
- un opérateur booléen :
and, or, nand, xor
- un opérateur unaire :
!
Filtre mutate
Ajout d’un tag
Le filtre mutate est un filtre “couteaux suisses” permettant une multitude de modifications.
Nous allons ajouter un tag à nos logs afin de différencier les recherches des ventes :
Conversion de type
Le filtre mutate permet de convertir certains champs en entier, flottant ou string.
Nous ajoutons à notre configuration la conversion des champs id et price :
Suppression d’un champ
Toujours avec le filtre mutate, nous allons supprimer le champ “msg”.
Nous avons en effet parsé ce champ avec le filtre kv et n’avons plus besoin de ce doublon d’information.
Ajoutez à la suite du dernier bloc de filtre :
Split d’un champ
Pour finir avec le filtre mutate, nous allons splitté notre champ “options” afin d’avoir un tableau d’options.
Au final, l’utilisation du filtre mutate nous a permis d’obtenir la sortie suivante :
GeoIP
Le filtre geoip permet d’ajouter des informations de géolocalisation via une adresse ip (ou hostname).
Logstash utilise la base de donnée GeoLite de Maxmind sous license CCA-ShareAlike 3.0.
Ici j’utilise une version de GeoLite City (format Binary / GZip) téléchargée au préalable sur le site Maxmind plutôt que la version embarquée dans Logstash :
Logstash ajoute un champ geoip contenant les précieuses informations de géolocalisations :
GeoIP et Bettermap
Le panel Bettermap de Kibana requiert un champ contenant les coordonnées GPS au format Geo_JSON (format : [ longitude, latitude ]).
Nous allons ajouter un champ “geoip.lnglat” contenant le tableau de coordonnées via le “hack” suivant :
Configuration Logstash finale
Pour rappel, voici le contenu final du fichier de configuration de Logstash :
La configuration finale de logstash parsera tous les logs générés dans le dossier /tmp/logstash. Vous pouvez lancer la génération de logs via la commande :
Elasticsearch
Nous allons installer Elasticsearch ainsi que le plugin head afin de stocker nos logs. Nous utiliserons ici la version 0.90.3, comme recommandé dans la documentation Logstash (pour les sorties elasticsearch & elasticsearch_http):
Il ne nous reste plus qu’à lancer Elasticsearch :
Vous pouvez visualiser votre cluster Elasticsearch via le plugin head à l’adresse : http://localhost:9200/_plugin/head
Par défaut, Logstash enverra vos logs dans des indices Elasticsearch nommés “logstash-YYYY-MM-DD”.
Template de mapping Elasticsearch
Elasticsearch ne nécessite aucune configuration particulière pour fonctionner avec Logstash. Cependant, pour cet exemple, nous allons désactiver l’analyseur utilisé sur certains champs. Cela s’avère utile pour notre dashboard Kibana qui utilise notamment des panels de type “terms”.
Cette requête désactive l’analyseur pour les champs “ip”, “name”, “model”, “options” et “email”. Cela vous évitera des écueils lors de l’affichage des “top clients” ou “top produits”:
Kibana
Pour installer Kibana, il vous faut également un serveur web. L’exemple est donné pour une installation standard d’Apache, mais tout autre serveur web capable de servir des fichiers statiques fera l’affaire.
Vous pouvez désormais accéder à Kibana à l’adresse : http://localhost/kibana
Un dashboard pré-configuré est disponible en téléchargement ici : dashboard.json
Il ne vous reste plus qu’à charger le dashboard via le menu Load > Advanced > Local File.
Sur cette capture d’écran, nous remarquons notamment que :
- Il y a 20% de ventes, et 80% de recherches
- 35% des clients sont des femmes
- 39% des produits vendus sont des baladeurs
- 254 iPod Touch ont été vendus pour la période de temps sélectionnée
- 3 requêtes (recherche ou vente) viennent des Etats-Unis
Pour aller plus loin
Des filtres peuvent être créés dynamiquement en cliquant sur les différents éléments du dashboard (notamment les petites loupes). Ils apparaissent dans le panel filtering sous forme de boîtes. En quelques clics, vous pouvez restreindre les résultats de vos queries sur un modèle, une option particulière, ou tout autre champ disponible. Vous aurez notamment la possibilité de suivre l’évolution des achats de téléphone Nexus 4 (modèle 16 Go, couleur Blanc) effectués par des femmes habitant sur Paris pour la période du 15 novembre au 25 décembre.
Sources
- http://bryanw.tk/2013/geoip-in-logstash-kibana
- http://elasticsearch-users.115913.n3.nabble.com/need-count-of-terms-using-facets-taking-space-into-account-td3956699.html
- https://gist.github.com/deverton/2970285
- http://untergeek.com/2012/09/20/using-templates-to-improve-elasticsearch-caching-with-logstash/