Utilisation de piwik en temps différé

Comment analyser le trafic d'un site internet sans le ralentir ?

17 février 2015

Exemple d'utilisation

Une solution comme Google analytics impose que les données d'analyses soient stockées chez Google.

Nous souhaitions que les informations de trafic de notre site internet soient stockées chez nous, nous avons opté pour le logiciel libre piwik.

Toutefois, pour une analyse en temps réel et sans ralentissement, piwik nécessite un serveur dédié qui occasionne un coût supplémentaire.

Les logs du serveur qui héberge notre site internet contiennent toutes les informations de connexion nécessaires à une analyse ultérieure du trafic.

Nous avons donc installé piwik sur un ordinateur local, et programmé un import automatique chaque nuit des logs du site internet.

Nous avons utilisé cette méthode pour analyser le trafic de notre projet lyon.glicer.com.

Pré-requis

Sur l'ordinateur local, les outils ci-dessous doivent être installés :

un serveur http qui hébergera piwik du type apache , nginx ou lighttpd, ce sont des logiciels libres.

php, ce langage libre est utilisé par piwik. (Si vous êtes sous windows, vous pouvez installer un package wamp qui contient apache et php).

piwik, ce logiciel libre permet d'analyser les logs du site internet.

python, ce langage libre est utilisé par le script d'importation de piwik.

Configuration

Identifiant piwik des sites

Nous avons besoin de 2 types d'analyses :

Depuis l'interface de piwik (page paramètres et onglet sites), nous avons créé un site par type d'analyse :

Les ids sont affectés et affichés par piwik, ils seront utilisés plus bas.

Configurer les pages internet

Dans chaque page internet, configurer et intégrer le fichier piwik.js situé dans le répertoire d'installation de piwik.

Il permet d'enregistrer les actions effectuées depuis un navigateur et les envoyer théoriquement à un serveur piwik dédié.

Mais dans notre cas nous l'utilisons pour enregistrer ces actions dans les logs et les importer ultérieurement.

Par exemple, dans chaque page html, intégrer le code ci-dessous :

//liste des options passée à piwik.js
<script>
    var _paq = _paq || [];
    _paq.push(['setSiteId', 4]);                    // identifiant du site glicerjs enregistré dans piwik, noté plus haut
    _paq.push(['appendToTrackingUrl', 'ua=' + encodeURIComponent(navigator.userAgent)]); // ajoute dans les logs le nom du navigateur utilisé
    _paq.push(['trackPageView']);                   // enregistre un évènement à chaque page visitée
    _paq.push(['enableLinkTracking']);              // enregistre un évènement à chaque lien cliqué
    _paq.push(['setTrackerUrl', '/piwik.php']);     // url vers laquelle envoyer les requêtes, ici /piwik.php
</script>

//ajout du client javascript de piwik
<script type="text/javascript" src="piwik.js"></script>

Configurer le serveur du site internet

piwik est installé sur un ordinateur local, /piwik.php n'est donc pas accessible depuis le serveur hébergeant le site internet.

Pour inscrire les requêtes piwik sans erreur dans les logs, il faut configurer le serveur internet qui répondra par un code 204 à chaque requête sur piwik.php.

Le code 204 indique une requête traitée avec succès sans information à renvoyer.

Par exemple, pour Apache, ajouter dans le fichier .htaccess la configuration ci-dessous :

RedirectMatch 204 piwik.php(.*)$

Traitement

Télécharger les logs

Soit manuellement à l'aide d'un client ftp, par exemple FileZilla Client qui est libre.

Soit à l'aide d'un script qui sera exécuté quotidiennement à l'aide de cron sous linux ou du planificateur de tâche sous windows.

Exemple de script en php :

<?php
    include('Net/SFTP.php');                                // librairie ftp libre http://phpseclib.sourceforge.net/

    $ftplogfile     = '/lamp0/var/log/apache/access.log';   // chemin du log apache sur le serveur
    $locallogfile   = 'C:\tmp\access.log';                  // nom du fichier local

    $ftp_server     = "ftp.glicer.com";                     // adresse ftp du serveur qui héberge le site internet
    $ftp_user       = "admin";                              // nom d'utilisateur autorisé à se connecter par ftp
    $ftp_pass       = "password";                           // mot de passe de l'utilisateur

    $sftp = new Net_SFTP($ftp_server);
    if (!$sftp->login($ftp_user, $ftp_pass)) {              // connexion au serveur ftp
        throw new \RuntimeException("Login Failed to " . $ftp_server);
    }

    $sftp->get($ftplogfile, $locallogfile);                 // téléchargement du fichier

Problème de doublons

Si le même log est importé plusieurs fois dans piwik, les analyses seront erronées, par exemple, si le même fichier log est importé deux fois, le nombre de visites sera doublé.

Pour remédier à ce problème et uniquement importer les nouveaux logs, les 2 solutions ci-dessous sont possibles :

Soit le serveur internet est configuré pour effectuer périodiquement une rotation des logs, par exemple avec apache sous linux, il est possible d'utiliser la commande graceful qui va conserver les anciens logs et inscrire les logs suivants dans un nouveau fichier.

Exemple d'utilisation de la commande graceful ci-dessous :

mv access_log new_access.log        // renomme le fichier log
apachectl graceful                  // demande de réinitialisation du fichier log
sleep 600
gzip new_access.log                 // fichier log qui sera importé dans piwik

Soit une fois le fichier log téléchargé, effectuer un pré-traitement sur le poste local qui générera un nouveau fichier log, ce dernier contiendra uniquement les nouvelles informations depuis la dernière importation dans piwik.

<?php
define("LASTLINEFILE", 'lastline.log');

/**
 * récupère la dernière ligne
 *
 * @return string
 */
function getLastLine()
{
    if (!file_exists(LASTLINEFILE)) {
        return '';
    }

    $fp   = fopen(LASTLINEFILE, 'r');
    $line = fgets($fp, 4096);
    fclose($fp);

    return trim($line);
}

/**
 * mise à jour de la dernière ligne
 *
 * @param string $line
 */
function updateLastLine($line)
{
    $fp = fopen(LASTLINEFILE, 'w');
    fputs($fp, trim($line));
    fclose($fp);
}

/**
 * créer un nouveau fichier log contenant uniquement les nouvelles données
 *
 * @param string $logfile
 * @param string $logupdate
 *
 * @return bool
 */
function createLogUpdate($logfile, $logupdate)
{
    $lastline = getLastLine();

    $srchandle     = fopen($logfile, "r");
    $dsthandle     = fopen($logupdate, "w");
    $nbrlines      = 0;
    $nbrlinestotal = 0;
    $previousline  = null;

    if (strlen($lastline) <= 0) {
        $startcopy = true;
    } else {
        $startcopy = false;
    }

    while (($line = fgets($srchandle, 4096)) !== false) {
        if ($startcopy) {
            fputs($dsthandle, $line);
            $nbrlines++;
        }

        $line = trim($line);
        if ($line === $lastline) {
            $startcopy = true;
        }

        $previousline = $line;
        $nbrlinestotal++;
    }
    fclose($srchandle);
    fclose($dsthandle);
    updateLastLine($previousline);

    if (!$startcopy) {
        copy($logfile, $logupdate);
        $nbrlines = $nbrlinestotal;
    }

    echo "Nbr nouveau logs : " . $nbrlines;

    return true;
}

createLogUpdate('c:\tmp\access.log', 'c:\tmp\new_access.log');

Importer les logs

Les lignes de commandes ci-dessous sont à exécuter à partir du répertoire piwik\misc\log-analytics\

Pour importer les logs relatifs aux actions du navigateur :

python import_logs.py --replay-tracking --enable-reverse-dns --url=http://localhost/piwik --idsite=4 "C:\tmp\new_access.log"

Pour importer les logs relatifs aux erreurs, aux redirections, aux robots, ... :

python import_logs.py --enable-http-errors --enable-http-redirects --enable-static --enable-bots --enable-reverse-dns --exclude-path=*piwik* --url=http://localhost/piwik --idsite=5 "C:\tmp\new_access.log"

Vérifier depuis l'interface de piwik que les données ont bien été importées.

Remarques

L'hébergeur peut avoir mis en place un serveur de cache qui se trouve devant le serveur internet, par exemple Varnish.

Le serveur de cache est chargé de répondre plus rapidement et décharger le serveur internet de certaines demandes, ces demandes seront inscrites dans les logs du serveur de cache mais elles seront absentes des logs du serveur internet et donc non visibles dans piwik.

Il est nécessaire d'intégrer les logs du serveur de cache ou de configurer votre serveur internet pour au moins ne pas mettre en cache les fichiers .html.

Par exemple, avec apache, ajouter dans le fichier .htaccess :

<FilesMatch "\.(htm|html)$">
    Header add Cache-Control "max-age=1"
</FilesMatch>

Versions des logiciels et langages utilisés