All pastes #476792 Raw Edit

Untitled

public text v1 · immutable
·published 2007-05-08 10:15 UTC
rendered paste body
/**
 * File contains strictly only Logger singleton class.
 *
 * Please check {@link Logger} for more information.
 *
 * This file is onften required.
 * @author James PIC <is_null@devangels.org>
 * @copyright James PIC 
 * @version 1.0
 * @package Logger
 */
/**
 * Logging API.
 * <p>This is a singleton class, this means that you can access the instance with : Logger::GetInstance().</p>
 * <p>For example :</p>
 * {@example /mnt/data/workspace/TemplateShop/examples/logger.example.php}
 * <p>Note that this class is used in NiceLogin to take care of the user interface, and to assure security in {@element NiceLogin::SecureClass()}.</p>
 * @author James PIC <is_null@devangels.org>
 * @copyright James PIC 
 * @version 1.0
 * @global array $aLoggerConfig
 * @uses DBLayer
 * @uses NiceLogin
 * @todo Remove the line argumnent
 */
function get_microtime()
{
    list($usec, $sec) = explode(' ', microtime());
    return ((float)$usec + (float)$sec);
}

class Logger
{
    /**
     * Logger instance
     * @access          private
     * @var             object
     */
    private static $_instance;
    /**
     * Instance of the database abstraction layer
     * @access          private
     * @var             object
     */
    private $_oDBLayer;
    /**
     * NiceLogin instance
     * @access          private
     * @var             object
     */
    public $_oUserLayer;
    /**
     * Event counter
     * @access          public
     * @var             integer
     */
    public $iEvent = 0;
    /**
     * Array where messages are stored in chronological order
     * @access          public
     * @var             array
     */
    public $aLogChrono;
    /**
     * Array where messages are stored in levels order
     * @access          public
     * @var             array
     */
    public $aLogLevels;
    /**
     * Array where messages are stored by function
     * @access          public
     * @var             array
     */
    public $aLogFunction;
    /**
     * Local microtimestamp
     * @access          public
     * @var             integer
     */
    public $micronow;
    /**
     * Local timestamp
     * @access          private
     * @var             integer
     */
    public $now;
    /**
     * User possible Ip
     * @access          public
     * @var             string
     */
    public $sUserIP;
    /**
     * Class constructor
     * @uses DBLayer
     * @uses NiceLogin
     * @uses $now
     */
    function __construct() 
    {
        global $db, $now, $aLoggerConfig;

        $this->_oDBLayer                 =&  $db;
        list($usec, $sec)                =  explode(' ', microtime());
        $this->micronow                  =  ((float)$usec + (float)$sec);
        $this->now                       =&  time();
        $now                             =&  $this->now;
        $this->sUserIP                   = (!empty($_SERVER['X_FORWARDED_FOR'])) ? $_SERVER['X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
        // Error id ir used in databse, because this kind of table grow very fast
        $aLoggerConfig['aErrorLevelIds'] = array_flip($aLoggerConfig['aErrorLevels']);
    }

    /**
     * Return the logger instance
     * @uses Logger::$_instance
     */
    public static function GetInstance() 
    { 
        if (!isset(self::$_instance)) 
        { 
            self::$_instance = new Logger() ;
        }
        return self::$_instance;
    }

    /**
     * Main method to log messages and data.
     * If the title of the event level to log is in $aLoggerConfig['aLogLevels'], database log occurs.
     * Logger::$aLogChrono is increment
     * @param       array       Executed function arguments
     * @param       string      Event label (for example function name)
     * @param       integer     Line Number
     * @param       string      Additionnal description
     * @param       int|string  Level id or label (default : debug_notice)
     * @uses $aLoggerConfig
     * @uses DBLayer
     * @uses Logger::$aLogChrono
     * @uses Logger::$aLogLevels
     * @uses Logger::$aLogFunction
     * @uses Logger::$iEvent
     * @uses Logger::$_instance
     */
    public function Log($r_func_args, $s_event_label, $str_line, $str_description='Begin', $m_level=NULL)
    {
        global $aLoggerConfig, $NLC;
        if (is_null($m_level)) $i_level = $aLoggerConfig['aErrorLevelIds']['debug_notice'];
        elseif (!is_numeric($m_level)) $i_level = $aLoggerConfig['aErrorLevelIds'][$m_level];
        else $i_level = $m_level;

        if (in_array($aLoggerConfig['aErrorLevels'][$i_level], $aLoggerConfig['aLogLevels']))
            $this->_oDBLayer->query('INSERT INTO `'.$this->_oDBLayer->prefix.'log` SET
            `sUserIP` 		        = \''.$this->_oDBLayer->escape($this->sUserIP).'\' ,
            `iDateEvent` 		= '.$this->_oDBLayer->escape($this->now).' ,
            `sFunction` 		= \''.$this->_oDBLayer->escape($s_event_label).'\' ,
            `iLevel` 		        = \''.$this->_oDBLayer->escape($i_level).'\' ,
            `sDescription` 	        = \''.$str_description.'\'') or $this->Log(func_get_args(), __FUNCTION__, __LINE__, $this->_oDBLayer->error());

        $this->aLogChrono[$this->iEvent][$s_event_label][$i_level]['description']			= $str_description;
        $this->aLogChrono[$this->iEvent][$s_event_label][$i_level]['level']			        = $aLoggerConfig['aErrorLevels'][$i_level];
        if ($str_description=='Begin' && $r_func_args)
            $this->aLogChrono[$this->iEvent][$s_event_label][$i_level]['arguments']		        = $r_func_args;
        if (is_object($NLC)&&$NLC->aUserData)
            $this->aLogChrono[$this->iEvent][$s_event_label][$i_level]['user data']			= $this->_oUserLayer->aUserData;
        if (is_object($NLC)&&$NLC->aCookie)
            $this->aLogChrono[$this->iEvent][$s_event_label][$i_level]['cookie data']			= $this->_oUserLayer->aCookie;
        $this->aLogChrono[$this->iEvent][$s_event_label][$i_level]['time']			        = $this->now;
        $this->aLogChrono[$this->iEvent][$s_event_label][$i_level]['microtime']			        = get_microtime();
        if ($this->iEvent)
        {
            $a = array_keys($this->aLogChrono[$this->iEvent-1]);
            $this->aLogChrono[$this->iEvent][$s_event_label][$i_level]['microtime_since_previous']
            = $this->aLogChrono[$this->iEvent][$s_event_label][$i_level]['microtime']
            -$this->aLogChrono[$this->iEvent-1][$a][$i_level]['microtime'];
        }
        if ($this->iEvent)
        $this->aLogChrono[$this->iEvent][$s_event_label][$i_level]['microtime_since_beginning']	        = $this->micronow-$this->aLogChrono[$this->iEvent-1][$s_event_label][$i_level]['microtime'];

        if (!isset($this->aLogLevels[$i_level]) || !isset($this->aLogLevels[$i_level][$s_event_label]) || !in_array($str_description, $this->aLogLevels[$i_level][$s_event_label]))
            $this->aLogLevels[$i_level][$s_event_label][]				                = $str_description;

        $this->aLogFunction[$s_event_label][$i_level][] = $str_description;

        $this->iEvent++;
    }

    /**
     * Returns true if $str_function casted a log with level $i_level
     * @param   integer Level Id
     * @param   string  Function name 
     * @uses Logger::$aLogFunction
     * @return  bool
     */
    public function ErrorLogged($i_level, $str_function)
    {
        if (isset($this->aLogFunction[$str_function])&&isset($this->aLogFunction[$str_function][$i_level])&&is_array($this->aLogFunction[$str_function][$i_level]))
            return true;
        else
            return false;
    }

    /**
     * Prints chronologic log
     * @param   string Error level string
     * @uses Logger::$aLogFunction
     * @return  bool
     */
    public function ShowLog($s_error_level='any')
    {
        $i_total_time = get_microtime() - $this->micronow;
        $str_output = '';
        $str_output .= "<font size='1'><table border='1' width='700px' cellspacing='0' cellpadding='1'><tr><th align='left' bgcolor='#f57900' colspan='5'><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>Logger</th></tr>";
        $str_output .= "<tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>";
        $str_output .= "<tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Percent of script</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align='left' bgcolor='#eeeeec'>Location</th></tr>";
        foreach ($this->aLogChrono as $i_event => $a_events)
        {
            foreach ($a_events as $s_event => $a_event)
            {
                foreach ($a_event as $i_level => $a_logged)
                {
                    if ($a_logged['microtime_since_previous']!=$i_total_time)
                        $str_output .= "<tr><td bgcolor='#eeeeec' align='center'>".$i_event."</td><td bgcolor='#eeeeec' align='center'>".(round(($a_logged['microtime_since_previous']/$i_total_time)*100,2))."</td><td bgcolor='#eeeeec' align='right'>".$a_logged['microtime_since_previous']." : ".$a_logged['microtime_since_previous']."</td><td bgcolor='#eeeeec'>".$a_logged['description']."</td><td title='/mnt/data/workspace/TemplateShop/examples/logger.example.php' bgcolor='#eeeeec'>".$s_event."</td></tr>";
                }
            }
        }
        $str_output .= '</table></font>';
        echo $str_output;
        //print_r($this->aLogChrono);
    }
 
    /**
     * Function to return notices if there are any.
     * If function returns false, it's a good idea to to use Logger::ReturnSuccessNotices().
     * Default : [ error, user_notice, user_error ], all functions
     * @param   array   Array of interresting levels, default are error levels
     * @uses Logger::$aLogLevels
     * @uses $aLoggerConfig
     * @return  bool
     */
    public function ReturnNotices($r_levels = NULL)
    {
        global $aLoggerConfig;
        if (!is_null($r_levels) && is_numeric($r_levels))
            $r_levels = array($r_levels);
        if (is_null($r_levels) || !is_array($r_levels) || (is_array($r_levels) && count($r_levels)<1))
            $r_levels = array($aLoggerConfig['aErrorLevelIds']['error'], $aLoggerConfig['aErrorLevelIds']['user_notice'], $aLoggerConfig['aErrorLevelIds']['user_error']);

        $a_logs = array();
        foreach ($r_levels as $i_level)
        {
            if (isset($this->aLogLevels[$i_level]))
                $a_logs += $this->aLogLevels[$i_level];
        }

        if (is_array($a_logs) && count($a_logs)>0)
            return $a_logs;
        return false;
    }

    /**
     * Function to return success notices if there are any.
     * @uses Logger::$aLogLevels
     * @uses $aLoggerConfig
     * @return  bool
     */
    public function ReturnSuccessNotices()
    {
        global $aLoggerConfig;
        return $this->ReturnNotices($aLoggerConfig['aErrorLevelIds']['success_notice']);
    }
}
?>