Intermédiaire

ASP.NET : Monitorer vos applications avec ELK

logo-elasticDe nos jours, les logs et traces font partie d’une étape importante dans le développement d’une application. La nécessité de détecter et de réagir rapidement en cas d’anomalie requiert de mettre en place une solution de monitoring robuste, capable de stocker, d’analyser et de lire ces logs. Aujourd’hui, nous allons voir comment mettre en place une plateforme de logging basée sur la stack ELK pour monitorer nos applications ASP.NET.

ELK : kézako

ELK est l’acronyme des 3 produits phares de la société Elastic :

  • Elasticsearch servira de support de stockage. Il est reconnu pour sa capacité à ingérer des volumes de données conséquents.

  • Logstash est la brique centrale de notre solution. On peut la voir comme un routeur de message. Ici, elle s’occupera de récupérer les logs, de les normaliser pour ensuite les déverser dans elasticsearch.

  • Kibana est la dernière brique de la solution. Elle permet de visualiser les logs collectés, de créer des visualisations pour ensuite les agréger dans des dashboards.

La combinaison de ces 3 produits va nous permettre de mettre en place une solution de logging performante.

Le code source et les configurations associées à la démo sont disponibles à l’adresse suivante : Github Soat.

Installation de l’environnement

La première étape avant de commencer à installer ELK est l’installation du JDK.

Une fois celui-ci installé, ajoutez une variable d’environnement JAVA_HOME pointant sur l’installation du JDK.

JDK Home

Nous pouvons maintenant commencer l’installation d’ELK !
Récupérez les install sur les urls suivantes : Elasticsearch, Logstash et Kibana.

On commence par installer Elasticsearch : pour cela exécutez service.bat. Un nouveau service va être installé et sera disponible dans les services windows (services.msc)

Pour installer Logstash et Kibana, nous allons utiliser un logiciel nommé NSSM, qui permet d’exécuter n’importe quel exécutable comme un service windows.

Rendez-vous sur NSSM pour récupérer le logiciel, puis ajoutez le dossier dans la variable PATH

Pour installer Kibana, lancez la commande suivante :
nssm install kibana

Sur la fenêtre qui apparaît, faites pointer le chemin sur le fichier kibana.bat

NSSM Install

Pour logstash, il faut créer 2 fichiers dans le répertoire bin après avoir extrait le zip.

  • logstash.config qui contiendra la config de logstash
  • service.bat qui sera la commande exécutée lors du démarrage du service windows. Ce fichier contient la commande suivante :
logstash.bat agent -f logstash.config

On spécifie seulement à logstash de charger le fichier de config que l’on vient de créer.
Une fois les installations terminées, nous pouvons passer à la configuration de logstash.

Configuration

Passons maintenant à la configuration de logstash. Un fichier de configuration logstash contient 3 types de sections :

  • Input : Cette section permet de configurer comment logstash va récupérer les logs. Il existe une multitude de connecteurs déjà disponibles avec l’installation de logstash, qui répondra sûrement à votre demande.

  • Filter : Cette section permet d’agir sur les logs récupérés en input. On va pouvoir, par exemple, parser le log pour ajouter un ou plusieurs champs, ou encore supprimer certains logs selon une condition, ajouter des données géographiques selon l’ip contenue dans un champ etc… C’est assez puissant et tout comme les inputs, il existe déjà des plugins disponibles !

  • Output : La dernière partie, comme vous pouvez l’imaginer, permet de configurer la sortie. C’est à dire l’endroit où l’on souhaite déverser nos logs que logstash aura reçu en entrée puis modifier selon le besoin. En sortie de logstash, on pourrait par exemple, produire un fichier au format CSV, appeler une url en HTTP, écrire un message sur IRC ou HipChat. Bref, il existe différente solution pour stocker nos logs. Pour voir un aperçu des plugins disponibles : https://www.elastic.co/guide/en/logstash/current/input-plugins.html

Dans notre application ASP.NET, en plus de vouloir stocker les logs dans Elasticsearch, nous allons également séparer les différents types de logs dans des index différents. Sur notre site, nous allons avoir :

  • Des logs techniques, utiles pour faire remonter les exceptions et utilisés par l’équipe support en cas d’anomalie

  • Des logs de performances, pour monitorer et détecter des latences anormales

  • Des logs business, pour créer des dashboard sur l’usage des fonctionnalités de notre site

L’intérêt de séparer dans des index différents va nous permettre d’appliquer une stratégie différente sur la rétention des données et donc gagner en performance lors des recherches dans kibana.
On pourrait ainsi appliquer la stratégie suivante :

  • Les logs techniques pourraient être conservés 1 mois

  • Les logs de performance, 15 jours

  • Les logs business, 1 an, voire plus

Nous allons définir une configuration pour l’input, qui sera un listener UDP, un filter, qui analysera la chaîne du user agent, et une configuration pour l’output qui déversera les logs dans elasticsearch, selon le type de log (technical, performance, business)

Le fichier logstash.config ressemble donc à ça :


input {
    udp {
        port => 12300 //port du listener
        codec => json //le format des logs que l'on recoit
        type => "logs" 
        add_field => ["env", "DEV"] //on ajoute un champs 'env' à tous nos logs 
    }
}
filter {
  useragent {
    source => "[properties][s-useragent]" //proprieté contenant la chaine du useragent (ce champs sera fourni par l'application ASP.NET)
    target => "browserInfo" // proprieté ou sera stocké l'extraction des informations concernant le navigateur
  }
}
output {
    elasticsearch {
        hosts => ["192.168.1.64:9200"] // IP:PORT du elasticsearch (9200 port par défaut)
        index => "%{[properties][type]}-%{+YYYY.MM.dd}" //on specifie l'index de notre log. On concatene le type du log + la date
        document_type => "%{[properties][type]}" //on type le log
        workers => 1  
    }
}

Une fois terminé, vous pouvez démarrer les 3 services. Si tout fonctionne, vous devriez pouvoir accéder à elasticsearch via http://localhost:9200 et à kibana via http://localhost:5601.

Nous pouvons maintenant passer à la dernière partie, l’intégration avec notre application ASP.NET !

Intégration dans notre application

La partie logging coté ASP.NET sera gérée via log4net qui est une librairie assez répandue dans le monde .NET.

Au niveau des librairies, nous allons donc avoir besoin de log4net et log4net.Ext.Json, afin de pouvoir serializer le log dans un format JSON pour le transmettre à logstash. La serialization n’est pas obligatoire car on pourrait très bien avoir un filtre coté logstash qui analyse le log.
Pour l’installation des 2 packages, il suffit d’ouvrir sa console nuget et d’exécuter les 2 commandes suivantes :

Install-Package log4net
Install-Package log4net.Ext.Json

Une fois installé, il ne manque plus qu’à configurer log4net. Rappelez-vous, nous avons configuré logstash avec un listener UDP. On a donc juste besoin de configurer une appender UDP log4net !

La configuration log4net est la suivante :


<log4net>
    <appender name="DebugAppender" type="log4net.Appender.TraceAppender">
        <layout type="log4net.Layout.SerializedLayout, log4net.Ext.Json">
            <default />
            <member value="properties" />  
        </layout>
    </appender>
    <appender name="UdpAppender" type="log4net.Appender.UdpAppender">
        <param name="RemoteAddress" value="192.168.1.64" /> //on fait pointer vers l'ip ou est installer logstash
        <param name="RemotePort" value="12300" /> //on specifie le port que l'on a mis dans la config logstash
        <layout type="log4net.Layout.SerializedLayout, log4net.Ext.Json">
            <default />
            <member value="properties" />  
        </layout>
    </appender>
    <root>
        <level value="INFO" />
        <appender-ref ref="DebugAppender" />
        <appender-ref ref="UdpAppender" />
    </root>
</log4net>

Il ne manque plus qu’à ajouter des logs dans notre application. On peut se faire une classe d’extension pour logger dans le bon index. Rappelez-vous, dans la config logstash, nous avons précisé que l’index se basait sur la propriété : properties[“type”] !


public static class LogExtensions
{
    private static void LogEvent(this ILog log, string message, IDictionary<string, object> properties, Level level, Exception ex = null)
    {
        var logEvent = new LoggingEvent(log.GetType(), log.Logger.Repository, log.Logger.Name, level, message, ex);
        foreach (var property in properties)
        {
            string key = property.Key;
            logEvent.Properties[key] = property.Value;
        }
        log.Logger.Log(logEvent);
    }

    public static void LogTechnical(this ILog log, string message, IDictionary<string, object> properties, Level level, Exception ex = null)
    {
        properties["type"] = "technical";
        log.LogEvent(message, properties, level, ex);
    }

    public static void LogBusiness(this ILog log, string message, IDictionary<string, object> properties)
    {
        var level = Level.Info;
        properties["type"] = "business";
        log.LogEvent(message, properties, level);
    }

    public static void LogPerf(this ILog log, long duration, IDictionary<string, object> properties)
    {
        var level = Level.Info;
        if (duration > 1000)
            level = Level.Warn;
        properties["duration"] = duration;
        properties["type"] = "performance";
        log.LogEvent($"Action took {duration} ms to be executed", properties, level);
    }
}   

Création du dashboard

L’installation et l’intégration sont terminées, nous pouvons passer à la partie sympathique : la création de nos dashboards, rendez-vous sur Kibana !

Ajout des indices

La première chose à effectuer, c’est de rajouter les sources de données, c’est à dire les indices où logstash ajoute les logs.
Il faut se rendre dans les settings puis indices. Ensuite on spécifie le pattern de l’index, ici ça sera technical-*, business-* et performance-*, et le champ contenant la date qui sera utilisé par kibana pour filtrer dans le temps.

Add Indice

Création des recherches

La création d’un dashboard passe par 3 étapes :

  • Une recherche : qui permet de filtrer et sélectionner un scope de logs

  • Une visualisation : qui affichera sous forme de graphe/tableau/compteur la représentation de la recherche sélectionnée

  • Un dashboard : qui agrège un ensemble de visualisation sur un même écran

Dans notre exemple, nous allons créer un dashboard pour visualiser le temps moyen de chargement des pages selon le navigateur.

Nous allons récupérer tous les logs de performances qui ont la propriété browser existante.

Pour savoir si une propriété existe sur un document, on peut utiliser la méthode exists:”property_name”

Dans notre cas, la recherche devient :
_exists_:"browserInfo.name"

On sauvegarde la recherche et on peut passer à l’etape 2, les visualisations.

Kibana query

Création des visualisations

A partir de la recherche sauvegardée, nous allons construire 2 graphes :

  • Un pour représenter la répartition des navigateurs

  • Un pour visualiser le temps moyen de chargement par url

Allez dans l’onglet Visualize, choisissez Pie Chart puis From a save search et sélectionnez la recherche faite précédemment.
Enfin, configurez le graph de façon à le séparer en fonction du nom du navigateur.

Kibana graph 1

Une fois fini, n’oubliez pas de sauvegarder le graphe.

Refaites un nouveau graphe mais, cette fois-ci, il s’agira d’un Area chart. Il nous permettra de visualiser facilement le temps moyen de chargement des pages par navigateur

Kibana graph 2

Une fois terminé, nous allons pouvons passer à la dernière étape, en allant sur l’onglet dashboard !

Création du dashboard

Cette étape est la plus simple, car il suffit juste de sélectionner les graphes que l’on a créés juste avant. Une fois ajoutés, vous devriez arriver au résultat suivant :

Capture8

Grâce au dashboard, nous pouvons remarquer que le temps moyen de chargement de la page Performance est anormalement long sur Chrome et Edge (~500ms), alors que sur les autres navigateurs nous sommes plus vers ~50ms.
Si nous regardons le code du projet, on peut remarquer que j’ai introduit de la latence volontairement pour Chrome (et que Edge est également reconnu comme un “Chrome”).

Cet article donne une introduction sur l’intégration de la stack ELK avec une application ASP.NET pour rendre le debugging et monitoring plus sympathique. Vous n’avez plus d’excuse pour ne pas l’intégrer dans votre projet ! Evidemment, la partie logging représente la première étape importante dans le monitoring de vos applications. On peut imaginer des scénarii plus complexes en ajoutant une brique pour gérer la rétention des logs ou encore la partie alerting qui permettra de rajouter de l’intelligence dans vos logs afin de pouvoir agir avant que les problèmes ne surviennent ! Nous aborderons ces deux sujets lors d’un prochain afin de devenir une légende des logs !

© SOAT
Toute reproduction interdite sans autorisation de la société SOAT

Nombre de vue : 1593

AJOUTER UN COMMENTAIRE