Laurent Kempé
Compteur de Hits sur votre site Web
Système de log des hits sur un site Web à l'aide de log4net et d'un module filtre http
Par Laurent Kempé publié le 10/04/2003 à 00:00, lu 8921 fois, 1 pages
Introduction
Cet article vous propose de découvrir une autre utilisation du framework log4net à travers la présentation d'une petite application permettant de récupérer des informations sur les visiteurs de votre site Web. Lors d'un précédant article je vous ai présenter le framework log4net je n'y reviendrais donc pas. Cet article utilise la dernière version de log4net : log4net 1.2.0 Beta 6.
Dans la première partie de l'article nous verrons comment écrire un module http qui nous permettra d'ajouter nos méthodes aux événements BeginRequest et EndRequest.
Puis nous écrirons une application de test.
Cette idée vient du fait que chez mon provider je n'ai aucun accès au log de IIS.
Http Module
Un http module nous permet d'enregistrer des événements intervenant lors de l'appel de l'application Web. C'est donc un bon emplacement pour mémoriser les visites des personnes navigant sur votre site.

Créer une application C# Web vide. Ajouter une référence à l'assembly log4net ainsi qu'à l'assembly System.Web.dll. Ajouter une classe C# au projet et nommer la 'HttpFilterLogs.cs'. Dans les proprietes de l'application changer la propriété 'Output Type' en 'Class Library'. Notre projet est prêt il ne reste plus qu'à éditer le source pour pouvoir créer notre module filtre http.

Pour cela éditer le fichier source 'HttpFilterLogs.cs'. Nous voulons créer une classe implémentant l'interface IHttpModule, pour cela nous avons besoin de faire une référence au namespace 'System.Web'. Nous utiliserons bien sure log4net donc nous ajoutons aussi une référence à ce namespace.
using System;
using System.Web;

using log4net;
Afin de pouvoir lire le fichier de configuration du framework log4net nous ajoutons l'attribut suivant:
// Load the configuration from the 'HttpFilterLogs.dll.log4net' file
[assembly: log4net.Config.DOMConfigurator(ConfigFileExtension="log4net", Watch=true)]
Notre classe hérite de l'interface IHttpModule qui définit deux méthodes : Init et Dispose.
La méthode Init nous permet d'initialiser notre module et de le préparer à réagir aux différents événements. La méthode Dispose quant à elle permet de libérer la mémoire utiliser par notre module si nécessaire. Voilà le squelette de la classe avec les deux méthodes:
/// <summary>
/// Class héritant de IHttpModule et implémentant le 
/// systéme de log de visites
/// </summary>
public class HttpFilterLogs : IHttpModule
{
    //Objet permettant d'écrire dans les logs
    private static readonly ILog log = LogManager.GetLogger(typeof(HttpFilterLogs));

    //Mémorisation de l'application appelant le module
    private HttpApplication httpApp;

    public void Init(System.Web.HttpApplication context)
    {
    }

    public void Dispose()
    {
    }
}
Nous avons ajouté une propriété « log » qui nous permettra de faire les logs des visites. Nous récupérons aussi l'application appelant le module dans la méthode Init que nous mémorisons dans la propriété « httpApp ».

Le module nous permet d'attacher nos handlers d'événements aux différents événements de la classe «System.Web.HttpApplication», par exemple «BeginRequest». L'événement «BeginRequest» est le premier des événements lors de l'arrivée d'une requête http sur notre application, il est dont le bon emplacement pour récupérer les informations concernant la requête. Nous attachons notre handler d'événement à l'aide du code suivant :
public void Init(System.Web.HttpApplication context)
{
    this.httpApp = context;

    this.httpApp.BeginRequest += new EventHandler(OnBeginRequest);
}

void OnBeginRequest(object sender, EventArgs a)
{
}
Il est temps de se pencher sur les informations que nous désirons stocker dans nos fichiers de logs et sur la méthode à utiliser.

Nous allons mémoriser dans les logs les informations suivantes :
  1. L'IP du visiteur
  2. Le nom du browser et sa version
  3. L'URL de la page demandée
  4. L'URL de la page précédente
Toutes ces informations sont disponibles en utilisant la classe « System.Web.HttpRequest » qui est une propriété publique de la classe « System.Web.HttpApplication » que nous récupérons et mémorisons dans l'implémentation de la méthode « Init » de notre module.

Afin d'avoir du code plus facile à maintenir et plus beau nous encapsulons la récupération de ces informations dans une classe que nous nommons « ClientInformations ». De plus nous la faisons hériter de la classe « log4net.ObjectRenderer.DefaultRenderer » du framework log4net. Cela nous permet de surcharger la méthode « ToString » pour faire la sortie de nos informations dans le fichier de log.

Nous ajoutons donc une référence au namespace :
using log4net.ObjectRenderer;
Puis la classe :
public class ClientInformations : DefaultRenderer
{
    System.Web.HttpRequest Request;

    public ClientInformations(System.Web.HttpRequest request)
    {
        this.Request = request;
    }

    public override string ToString()
    {
        string UrlReferer = Request.UrlReferrer.AbsoluteUri;

        string Ip = Request.UserHostAddress.Trim();

        string Browser = Request.Browser.Browser + 
                               Request.Browser.MajorVersion +
                               "." +
                               Request.Browser.MinorVersion;

        string RequestedUrl = Request.Url.ToString();

        return Ip + " " + Browser + " " + RequestedUrl + " " + UrlReferer;
    }
}
Il ne reste plus qu'à ajouter le traitement voulu lors de l'événement "OnBeginRequest".
C'est-à-dire l'écriture des informations sur le visiteur dans le fichier de logs.
void OnBeginRequest(object sender, EventArgs a)
{
    if (log.IsInfoEnabled)
    {
        log.Info( new ClientInformations(httpApp.Request) );
    }   
}
Pour finir il nous reste à créer le fichier de configuration de log4net. Ajouter un fichier XML au projet et nommer le « HttpFilterLogs.dll.log4net » puis ajouter le contenu suivant :
<?xml version="1.0" encoding="utf-8" ?>

<!-- This section contains the log4net configuration settings -->
<log4net>

    <!-- Define some output appenders --> 
    
    <appender name="LogFileAppender" type="log4net.Appender.FileAppender" >
        <param name="File" value="Visits-log.txt" />
        <param name="AppendToFile" value="true" />
        <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n" />
        </layout>
    </appender>

    <!-- Setup the root category, add the appenders and set the default level -->
    
    <root>
        <level value="DEBUG" />
        <appender-ref ref="LogFileAppender" />
    </root>

</log4net>
Dans mon cas j'ai utilisé l'appender log4net qui permet d'envoyer les logs grâce au Remoting de .NET afin de recevoir les logs sur ma propre machine.
Application de test
L'application de test est on ne peut plus simple puisqu'elle est juste constituée d'une application ASP.NET C# standard crée à l'aide du wizard de Visual Studio .NET. La seule différence c'est la modification du fichier web.config afin que l'aaplication utilise le module filtre http.

Ajouter au fichier « web.config » :
<system.web>

 <httpModules>
  <add name="HttpFilterLogs" type="HttpFilterLogs, HttpFilterLogs" />
 </httpModules>

</system.web>
Bien entendu votre assembly « HttpFilterLogs.dll » crée dans le chapitre précédent ainsi que l'assembly « log4net-net-1.0.dll » doivent se trouver dans le path de votre application.
Conclusion
Ceci est juste un petit exemple de ce qu'il est possible de faire à l'aide d'un module filtre http. De plus les informations concernant les visiteurs sont relativement basiques, mais rien ne vous empêche d'étendre cette application afin de la rendre plus à votre goût. On peut par exemple imaginer faire des logs du temps de rendu des pages. Il est aussi possible à l'aide des modules filtres http de créer des règles de compression de contenu, de nouvelle méthode d'authentification (par empreintes digitales par exemple).
 
» Démarrer une discussion