26-10-2010, 03:08 PM
Voici ma classe de log:
* le nom des fichiers logs (private $fileFormat='\R\t\s\P\h\P\G\a\m\e\r-Y-m-d.\l\o\g' est à adapter
* les méthodes getUserNom() et getUserId() doivent être reprise selon la gestion interne de l'utilisateur connecté.
* les méthodes de rendus (getUserTxt(), getIpTxt(), getDateTxt(), getLogTxt() et getEntete() ) sont à adapter selon le format de log souhaité
L'initialisation du log (au début du index.php):
L'utilisation du log:
Il y a aussi la possibilité de logger ponctuellement dans un autre fichier avec la méthode logFile().
PS: en bonus, j'ai créé une classe de base dont héritent toutes mes autres classes pour avoir à disposition le log:
<?php
/**
* Classe de gestion des Logs applicatifs
* Intègre le pattern SINGLETON
*
* @copyright 2010
* @author Myrina
* @version 1.0
*/
class Log {
/**
* Ce niveau sert pour ne rien logger
*
*/
const NONE = -1;
/**
* Ce niveau sert à logger que les erreurs qui interrompent le script
* (l'interception des erreurs PhP n'est pas implémentée pour l'instant)
*
*/
const FATAL = 0;
/**
* Ce niveau sert à logger les erreurs de fonctionnement
*
*/
const ERROR = 1;
/**
* Ce niveau sert à logger les comportements bizarres
*
*/
const WARN = 2;
/**
* Ce niveau sert à logger tout message informatif sur le fonctionnement
*
*/
const INFO = 3;
/**
* Ce niveau sert à logger tous les messages
*
*/
const DEBUG = 4;
/**
* Tableau des entêtes de messages selon la gravité de celui-ci
*
* @var Array
*/
private static $levelsTxt= array (
Log::FATAL => 'ERREUR FATAL',
Log::ERROR => 'ERREUR',
Log::WARN => 'AVERTISSEMENT',
Log::INFO => 'INFORMATION',
Log:EBUG => 'MODE DEBUG'
);
/**
* Niveau courant de logging des messages
*
* @var Integer
*/
private $logLevel=Log::INFO;
/**
* Format de génération des noms de fichier en respectant la syntaxe de la fonction <b>date()</b>
*
* @var String
*/
private $fileFormat='\R\t\s\P\h\P\G\a\m\e\r-Y-m-d.\l\o\g';
/**
* A <b>true</b> si le nom du fichier doit dépendre de la date du jour
*
* @var Boolean
*/
private $isDate=true;
/**
* Répertoire de stockage des fichiers logs
*
* @var String
*/
private $dir='logs';
/**
* Format d'affichage de la date et de l'heure pour les messages
*
* @var String
*/
private $dateFormat='d/m/Y H:i';
/**
* Utilisateur connecté
*
* @var User
*/
private $user=null;
/**
* Définit si l'adresse IP apparait dans le log ou pas
*
* @var Boolean
*/
private $logIp=false;
/**
* Retour à la ligne (ici pour Windows)
*
* @var String
*/
private $eol="\r\n";
/**
* Instance de la classe
*
* @var Listes
*/
private static $instance;
/**
* Constructeur privé afin d'empêcher la création direct par new
*
*/
private function __construct()
{
}
/**
* Méthode SINGLETON
*
* @return Log
*/
public static function getInstance()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
/**
* Prévient les utilisateurs sur le clônage de l'instance
*
*/
public function __clone()
{
throw new Exception('Le clônage n\'est pas autorisé.');
}
/**
* Choix du repértoire de stockage des logs
*
* @param String $dir Répertoire par défaut de stockage des fichiers de logging
*/
public function initDir($dir=null) {
//Vérification du répertoire par défaut
if ($dir!=null) {
$this->setDir($dir);
} else {
$this->setDir($this->dir);
}
}
/**
* Enregistre un message de log au niveau fourni
*
* @param Integer $logLevel Niveau du message (Log::...)
* @param String $mess Message à logger
*/
public function log($logLevel,$mess) {
if ($this->isToLog($logLevel)) {
$this->write($this->getEntete($logLevel).$mess);
}
}
/**
* Renvoi le niveau courant de logging
*
* @return Integer
*/
public function getLogLevel() {
return $this->logLevel;
}
/**
* Renvoi le texte du niveau courant courant de logging
*
* @return String
*/
public function getLogLevelTxt() {
return Log::$levelsTxt[$this->getLogLevel()];
}
/**
* Fixe le nouveau niveau courant de logging
*
* @param Integer $newLvl
*/
public function setLogLevel($newLvl) {
if ($this->isCorrectLevel($newLvl)) {
$this->logLevel=$newLvl;
}
}
/**
* Renvoi le répertoire de stockage des fichiers de logs
*
* @return String
*/
public function getDir() {
return $this->dir;
}
/**
* Change le répertoire de stockage des fichiers de logs
*
* @param String $newPath
*/
public function setDir($newPath) {
// $newDir=dirname(SITE_ROOTDIR.$newPath);
$newDir=dirname($newPath);
if ($newDir=='.') {
$newDir=$newPath;
}
//Si le répertoire n'existe pas
if (!is_dir($newDir)) {
//Si il peut être créé
if (mkdir($newDir,0777)) {
$this->dir=$newDir;
}
} else {
$this->dir=$newDir;
}
}
/**
* Modifie le nom du fichier de log
*
* @param String $file nom du fichier
* @param Boolean $useDate à <b>true</b> si le nom du fichier contient une date à formatter
*/
public function setFile($file,$useDate=true) {
$this->fileFormat=$file;
$this->isDate=$useDate;
}
/**
* Renvoi le chemin complet du fichier courant de logging
*
* @return String
*/
public function getCurrentFile() {
$file=$this->dir.'/'.($this->isDate?date($this->fileFormat,time()):$this->fileFormat);
return $file;
}
/**
* Renvoi le nom de l'utilisateur pour lequel le logging est actif
*
* @return String
*/
private function getUserNom() {
if (is_object($this->user) && ($this->user instanceof User)) {
return $this->user->getName();
} elseif (is_array($this->user)) {
return $this->user['username'];
} else {
return '';
}
}
/**
* Renvoi l'ID MySQL de l'utilisateur pour lequel le logging est actif
*
* @return Integer
*/
private function getUserId() {
if (is_object($this->user) && ($this->user instanceof User)) {
return $this->user->getId();
} elseif (is_array($this->user)) {
return $this->user['id'];
} else {
return '';
}
}
/**
* Associe l'utilisateur connecté aux messages de logging
*
* @param Mixed $user
*/
public function setUser($user) {
$this->user=$user;
}
/**
* A <b>true</b> si l'adresse IP doit apparaitre dans les messages de logging
*
* @return Boolean
*/
public function isLogIp() {
return $this->logIp;
}
/**
* Fixe le logging de l'adresse IP ou pas
*
* @param Boolean $logIp
*/
public function setLogIp($logIp) {
if (is_bool($logIp)) {
$this->logIp=$logIp;
}
}
/**
* Ecrit le message dans le fichier courant
*
* @param String $msg
*/
private function write($msg){
$txt=$msg.$this->eol;
$fp = fopen($this->getCurrentFile(), "a");
fputs($fp, $txt);
fclose($fp);
}
/**
* Vérifie si le niveau spécifié est connu par la classe
*
* @param Integer $level
* @return Boolean
*/
private function isCorrectLevel($level) {
return (in_array($level,array_keys(Log::$levelsTxt)));
}
/**
* Vérifie si le niveau spécifié est à logger
*
* @param Integer $level
* @return Boolean
*/
private function isToLog($level){
return ($this->isCorrectLevel($level)&&$level<=$this->getLogLevel());
}
/**
* Recherche l'IP de la personne connectée
*
* @return String Adresse IP
*/
private function getIp(){
$ip='';
if ($this->isLogIp()) {
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
// Si la requête HTTP a été forwardé par un proxy
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif(isset($_SERVER['HTTP_CLIENT_IP'])){
$ip = $_SERVER['HTTP_CLIENT_IP'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
}
return $ip;
}
/**
* Formattage du texte contenant les informations de l'utilisateur
*
* @return String
*/
private function getUserTxt() {
$txt='';
if ($this->user!=null) {
$txt=' ( '.$this->getUserNom().' -ID:'.$this->getUserId().')';
}
return $txt;
}
/**
* Formattage du texte contenant les informations de l'adresse IP
*
* @return String
*/
private function getIpTxt(){
$txt='';
$ip=$this->getIp();
if ($ip!='') {
$txt=' [IP:'.$ip.']';
}
return $txt;
}
/**
* Formattage du texte contenant la date du logging
*
* @return String
*/
private function getDateTxt(){
$txt='';
$date=date($this->dateFormat,time());
$txt=$date.'>';
return $txt;
}
/**
* Formattage du texte contenant le nom du niveau de log
*
* @param Integer $logLevel
* @return String
*/
private function getLogTxt($logLevel){
$txt='';
$log=Log::$levelsTxt[$logLevel];
$txt=' #'.$log.': ';
return $txt;
}
/**
* Renvoi la partie à logger avant le message
*
* @param Integer $logLevel
* @return String
*/
private function getEntete($logLevel){
return $this->getDateTxt().$this->getUserTxt().$this->getIpTxt().$this->getLogTxt($logLevel);
}
/**
* Enregistre un message de log au niveau fourni dans le fichier fourni
*
* @param String $file Nom du fichier de stockage
* @param Integer $logLevel Niveau du message (Log::...)
* @param String $mess Message à logger
*/
public function logFile($file,$logLevel,$mess) {
$tmpfile=$this->fileFormat;
$tmpdate=$this->isDate;
$this->setFile($file,false);
$this->log($logLevel,$mess);
$this->setFile($tmpfile,$tmpdate);
}
}
?>
Il faudra certainement prévoir des adaptations:* le nom des fichiers logs (private $fileFormat='\R\t\s\P\h\P\G\a\m\e\r-Y-m-d.\l\o\g' est à adapter
* les méthodes getUserNom() et getUserId() doivent être reprise selon la gestion interne de l'utilisateur connecté.
* les méthodes de rendus (getUserTxt(), getIpTxt(), getDateTxt(), getLogTxt() et getEntete() ) sont à adapter selon le format de log souhaité
L'initialisation du log (au début du index.php):
//Initialisation du logger
$log=Log::getInstance();
$log->initDir();
$log->setLogLevel(Log:EBUG);
L'utilisation du log:
$log=Log::getInstance();
$log->log(Log:EBUG,'String internationalisée non trouvée: '.$key);
Il y a aussi la possibilité de logger ponctuellement dans un autre fichier avec la méthode logFile().
PS: en bonus, j'ai créé une classe de base dont héritent toutes mes autres classes pour avoir à disposition le log:
<?php
/**
* Classe abstraite servant de base à toutes les classes et implémentant le mécanisme de log
*
* @copyright 2010
* @author Myrina
* @version 1.0
*/
abstract class BaseClass {
/**
* Enregistre un message de log au niveau fourni
*
* @param Integer $logLevel Niveau du message (Log::...)
* @param String $mess Message à logger
* @param Boolean $ip à <b>true</b> pour faire apparaître l'@ IP dans le log
*/
protected function log($logLevel,$mess,$ip=false) {
$log=Log::getInstance();
$class=get_class($this);
$svgIp=$log->isLogIp();
if ($ip) {
$log->setLogIp(true);
}
$log->log($logLevel,'('.$class.'):'.$mess);
$log->setLogIp($svgIp);
}
}
?>