Fichiers Log perso sous Laravel 4

Avec laravel 4, un package pour la gestion des logs est fournit: monolog.

Dans cet article, je propose de faire un fichier de logs personnel pour une utilisation particulière. Pour un suivit de nos utilisateurs de certaines fonctionnalités du site…

Une façon simple serait de créer un package avec un helper qui fonctionne exactement de la même façon que Log, par exemple un LogPerso::notice(‘un test’).

La, j’ai choisi une autre voie, faire un écouteur de messages qui enregistrera ces messages dans un fichier de Log particulier. Il sera déclenché par un appel du type :

\Event::fire(‘user.regarder’, array(‘des datas’));

1)  Créer un fichier particulier avec monolog

Un fichier monolog a un nom du type : Service- »Date_du_jour ».txt (log-test-2013-06-24.txt) et il est enregistré sous laravel dans le dossier /app/storage/logs/. Donc pour créer un objet Monolog je doit lui passé (au minimum) un nom de service. Dans notre classe ce sera la propriété $this->name

private function initLog()
{
        $this->log = new \Monolog\Logger($this->name);
        $this->log->pushHandler(
            new \Monolog\Handler\RotatingFileHandler(
                storage_path().'/logs/log-'.$this->name.''.'.txt',
                30,\Monolog\Logger::INFO)
            );
}

 

2) Ecrire dans notre fichier log perso

Notre classe LogPerso dispose d’un fichier, maintenant il ne nous manque plus qu’une méthode pour écrire dans ce fichier. Un message laravel est normalement de la forme « service.action », il nous faut donc une méthode qui prend en paramètres le message et des datas facultatives.

    public function handle($message,Array $datas=array())
    {
        list(,$action)= explode('.',$message);
        switch ($action){
        case 'delete':
            $this->log->addAlert($action,$datas);
            break;
        default :
            $this->log->notice($action,$datas);
        }
        return true;
    }

et voila notre classe de base est finie

<?php namespace App\controllers;

use \Monolog\Logger;
use \Monolog\Handler;

class LogPerso
{

    public $log;
    public $name='user';

    public function __construct($name)
    {
        $this->name=strtolower($name);
        $this->initLog();
    }

    /**
     * creation de l'objet Monolog
     */
    private function initLog()
    {
        $this->log = new \Monolog\Logger($this->name);
        $this->log->pushHandler(
            new \Monolog\Handler\RotatingFileHandler(
                storage_path().'/logs/log-'.$this->name.''.'.txt',
                30,\Monolog\Logger::INFO)
            );
    }

    /**
     *  Ecouteur d'evenements
     */
    public function handle($message,Array $datas=array())
    {
        list(,$action)= explode('.',$message);
        switch ($action){
        case 'delete':
            $this->log->addAlert($action,$datas);
            break;
        default :
            $this->log->notice($action,$datas);
        }
        return true;
    }
}

Utilisation de notre classe.

Pour nos test, je vais charger notre classe dans app/start/global.php.

use App\controllers;

\App::singleton('LogPerso', function() {
    return new App\controllers\LogPerso('test');
});

\Event::listen('test.*', function($param, $event) {
	App::offsetGet('LogPerso')->handle($event, array($param));
});

Nous créons une instance de notre classe puis créons un écouteur d’évènements qui déclenchera l’écriture dans notre fichier log. ici, notre service d’écoute-log s’appelle  »test ». Touts les messages débutant par « test. » seront enregistrés dans un fichier log particulier(log-test-date_du_jour.txt)

Il est possible de déclarer un Service Provider (fournisseurs de services) et utiliser notre classe en tant que classe écouteur puis de la déclarer uniquement dans config/app.php – providers.Il est possible aussi de ce créer son propre package.

Que fait notre classe maintenant ?

Elle écoute(en fait pas elle) tous les messages Laravel débutant par le mot « test. », et elle enregistre le message dans un fichier log : /storage/logs/log-test- »date_du_jour ».txt »

Vous désirez l’utiliser rien de plus facile ajoutez dans votre code plein de :
Event::fire(‘test.MonAction’, array(‘des datas’));
Event::fire(‘test.delete’, array(‘encore des datas’));

Ici, l’intérêt des évènements prend tout son sens car vous êtes indépendant de la classe LogPerso. Vous pouvez simplement ne plus écouter ces messages, ou les renvoyer dans le log général de Laravel, ou réécrire la classe LogPerso pour qu’elle envoie les messages dans la console de debug (firebug, phpconsole) plutôt que dans un fichier.


Réutilisons nos logs.

Une petite page d’administration pour admirer nos logs perso serait pas mal :)

Il nous faut en premier une méthode pour lire et transformer-interpréter nos logs, intégrons la dans notre classe  LogPerso :

   /**
     * retrouver le fichier log
     */
    public function getFile()
    {
        return storage_path().'/logs/log-'.$this->name.'-'.date('Y-m-d').'.txt';
    }

    /**
     * charger le fichier log dans un tableau
     */
    public function loadFile(/* $le_jour_voulu*/)
    {
        $log = array();
        $pattern = "/\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.*/";
        $log_levels=array(
            //'all' => 'all',
            'emergency' => 'EMERGENCY',
            'alert' => 'ALERT',
            'critical' => 'CRITICAL',
            'error' => 'ERROR',
            'warning' => 'WARNING',
            'notice' => 'NOTICE',
            'info' => 'INFO',
            'debug' => 'DEBUG'
        );
        $log_file = $this->getFile(/* $le_jour_voulu */);

        if ( file_exists($log_file)) {
            $file = \File::get($log_file);

            preg_match_all($pattern, $file, $headings);
            $log_data = preg_split($pattern, $file);

            unset($log_data[0]);            
            foreach ($headings as $h) {
                for ($i=0; $i < count($h); $i++) {
                    foreach ($log_levels as $ll) {
                            if (strpos(strtolower($h[$i]), strtolower($this->name.'.' . $ll)))
                            {
                                $log[$i+1] = array('level' => $ll, 'header' => $h[$i], 'stack' => $log_data[$i+1]);
                            }
                    }
                }
            }
        }

        unset($headings);
        unset($log_data);
        $log = array_reverse($log);//+ recent au + ancien
        return $log;
    }

Cette méthode charge automatiquement le fichier du jour! et ne reformate pas les messages : cela dépend en fait de chaque usage.
Et voila nous sommes prêts a afficher dans une vue notre beau fichier (avec les class css correspondantes).

$logs=App::offsetGet('LogPerso')->loadFile();

foreach($logs as $log){
	echo '<p class="'.$log['level'].'">'.
	'<b>'.$log['level'].'</b> '.$log['header'].
	'</p>';
}

 

Share Button

Vous devriez aimer...