/core/libraries/Log.php
PHP | 430 lines | 198 code | 45 blank | 187 comment | 27 complexity | 650dd69f21ee998ec893d75bfecf9983 MD5 | raw file
Possible License(s): LGPL-2.1
- <?php
- /**
- * Adapated from Klogger
- * Usage:
- * $log = new Log('/var/log/', Log::INFO );
- * $log->logInfo('Returned a million search results'); //Prints to the log file
- * $log->logFatal('Oh dear.'); //Prints to the log file
- * $log->logDebug('x = 5'); //Prints nothing due to current severity threshhold
- *
- * @author Kenny Katzgrau <katzgrau@gmail.com>
- * @since July 26, 2008
- * @link http://codefury.net
- * @version 0.1
- */
- /**
- * Class documentation
- */
- class Log
- {
- /**
- * Error severity, from low to high. From BSD syslog RFC, secion 4.1.1
- * @link http://www.faqs.org/rfcs/rfc3164.html
- */
- const EMERG = 0; // Emergency: system is unusable
- const ALERT = 1; // Alert: action must be taken immediately
- const CRIT = 2; // Critical: critical conditions
- const ERR = 3; // Error: error conditions
- const WARN = 4; // Warning: warning conditions
- const NOTICE = 5; // Notice: normal but significant condition
- const INFO = 6; // Informational: informational messages
- const DEBUG = 7; // Debug: debug messages
- //custom logging level
- /**
- * Log nothing at all
- */
- const OFF = 8;
- /**
- * Alias for CRIT
- * @deprecated
- */
- const FATAL = 2;
- /**
- * Internal status codes
- */
- const STATUS_LOG_OPEN = 1;
- const STATUS_OPEN_FAILED = 2;
- const STATUS_LOG_CLOSED = 3;
- /**
- * Current status of the log file
- * @var integer
- */
- private $_logStatus = self::STATUS_LOG_CLOSED;
- /**
- * Holds messages generated by the class
- * @var array
- */
- private $_messageQueue = array();
- /**
- * Path to the log file
- * @var string
- */
- private $_logFilePath = null;
- /**
- * Current minimum logging threshold
- * @var integer
- */
- private $_severityThreshold = self::INFO;
- /**
- * This holds the file handle for this instance's log file
- * @var resource
- */
- private $_fileHandle = null;
- /**
- * Standard messages produced by the class. Can be modified for il8n
- * @var array
- */
- private $_messages = array(
- //'writefail' => 'The file exists, but could not be opened for writing. Check that appropriate permissions have been set.',
- 'writefail' => 'The file could not be written to. Check that appropriate permissions have been set.',
- 'opensuccess' => 'The log file was opened successfully.',
- 'openfail' => 'The file could not be opened. Check permissions.',
- );
- /**
- * Default severity of log messages, if not specified
- * @var integer
- */
- private static $_defaultSeverity = self::DEBUG;
- /**
- * Valid PHP date() format string for log timestamps
- * @var string
- */
- private static $_dateFormat = 'Y-m-d G:i:s';
- /**
- * Octal notation for default permissions of the log file
- * @var integer
- */
- private static $_defaultPermissions = 0777;
- /**
- * Array of Log instances, part of Singleton pattern
- * @var array
- */
- private static $instances = array();
- /**
- * Partially implements the Singleton pattern. Each $logDirectory gets one
- * instance.
- *
- * @param string $logDirectory File path to the logging directory
- * @param integer $severity One of the pre-defined severity constants
- * @return Log
- */
- public static function instance($logDirectory = false, $severity = false)
- {
-
- if ($severity === false) {
- $severity = self::$_defaultSeverity;
- }
-
- if ($logDirectory === false) {
- if (count(self::$instances) > 0) {
- return current(self::$instances);
- } else {
- $logDirectory = dirname(__FILE__);
- }
- }
- if (in_array($logDirectory, self::$instances)) {
- return self::$instances[$logDirectory];
- }
- self::$instances[$logDirectory] = new self($logDirectory, $severity);
-
- return self::$instances[$logDirectory];
- }
- /**
- * Class constructor
- *
- * @param string $logDirectory File path to the logging directory
- * @param integer $severity One of the pre-defined severity constants
- * @return void
- */
- public function __construct($logDirectory, $severity)
- {
- $logDirectory = rtrim($logDirectory, '\\/');
- if ($severity === self::OFF) {
- return;
- }
- $this->_logFilePath = $logDirectory
- . DIRECTORY_SEPARATOR
- . 'log_'
- . date('Y-m-d')
- . '.txt';
- $this->_severityThreshold = $severity;
- if (!file_exists($logDirectory)) {
-
- $results = mkdir($logDirectory, self::$_defaultPermissions, true);
-
- # Show problem when in development
- if(!$results && !IN_PRODUCTION) {
- die("Failed to make a directory for logs; please create a writable directory at: ".LOG_PATH);
- }
- # Email problem when in production
- elseif(!$results && IN_PRODUCTION) {
- # Email app owner
- $subject = "Log Directory Error:".LOG_PATH;
- $body = "Failed to make a directory for logs; please create a writable directory at: ".LOG_PATH;
- Utils::alert_admin($subject, $body);
- die();
- }
- }
- if (file_exists($this->_logFilePath) && !is_writable($this->_logFilePath)) {
- $this->_logStatus = self::STATUS_OPEN_FAILED;
- $this->_messageQueue[] = $this->_messages['writefail'];
- return;
- }
- if (($this->_fileHandle = fopen($this->_logFilePath, 'a'))) {
- $this->_logStatus = self::STATUS_LOG_OPEN;
- $this->_messageQueue[] = $this->_messages['opensuccess'];
- } else {
- # Show problem when in development
- if(!IN_PRODUCTION) {
- die("Logging failed; please make the following directory writable: ".LOG_PATH);
- }
- # Email problem when in production
- else {
- # Email app owner
- $subject = "Log Permissions Error:".LOG_PATH;
- $body = "Logging failed; please make the following directory writable: ".LOG_PATH;
- Utils::alert_admin($subject, $body);
- die();
- }
-
- $this->_logStatus = self::STATUS_OPEN_FAILED;
- $this->_messageQueue[] = $this->_messages['openfail'];
- }
- }
- /**
- * Class destructor
- */
- public function __destruct()
- {
- if ($this->_fileHandle) {
- fclose($this->_fileHandle);
- }
- }
- /**
- * Writes a $line to the log with a severity level of DEBUG
- *
- * @param string $line Information to log
- * @return void
- */
- public function logDebug($line)
- {
- return $this->log($line, self::DEBUG);
- }
- /**
- * Returns (and removes) the last message from the queue.
- * @return string
- */
- public function getMessage()
- {
- return array_pop($this->_messageQueue);
- }
- /**
- * Returns the entire message queue (leaving it intact)
- * @return array
- */
- public function getMessages()
- {
- return $this->_messageQueue;
- }
- /**
- * Empties the message queue
- * @return void
- */
- public function clearMessages()
- {
- $this->_messageQueue = array();
- }
- /**
- * Sets the date format used by all instances of Log
- *
- * @param string $dateFormat Valid format string for date()
- */
- public static function setDateFormat($dateFormat)
- {
- self::$_dateFormat = $dateFormat;
- }
- /**
- * Writes a $line to the log with a severity level of INFO. Any information
- * can be used here, or it could be used with E_STRICT errors
- *
- * @param string $line Information to log
- * @return void
- */
- public function logInfo($line)
- {
- return $this->log($line, self::INFO);
- }
- /**
- * Writes a $line to the log with a severity level of NOTICE. Generally
- * corresponds to E_STRICT, E_NOTICE, or E_USER_NOTICE errors
- *
- * @param string $line Information to log
- * @return void
- */
- public function logNotice($line)
- {
- return $this->log($line, self::NOTICE);
- }
- /**
- * Writes a $line to the log with a severity level of WARN. Generally
- * corresponds to E_WARNING, E_USER_WARNING, E_CORE_WARNING, or
- * E_COMPILE_WARNING
- *
- * @param string $line Information to log
- * @return void
- */
- public function logWarn($line)
- {
- return $this->log($line, self::WARN);
- }
- /**
- * Writes a $line to the log with a severity level of ERR. Most likely used
- * with E_RECOVERABLE_ERROR
- *
- * @param string $line Information to log
- * @return void
- */
- public function logError($line)
- {
- return $this->log($line, self::ERR);
- }
- /**
- * Writes a $line to the log with a severity level of FATAL. Generally
- * corresponds to E_ERROR, E_USER_ERROR, E_CORE_ERROR, or E_COMPILE_ERROR
- *
- * @param string $line Information to log
- * @return void
- * @deprecated Use logCrit
- */
- public function logFatal($line)
- {
- return $this->log($line, self::FATAL);
- }
- /**
- * Writes a $line to the log with a severity level of ALERT.
- *
- * @param string $line Information to log
- * @return void
- */
- public function logAlert($line)
- {
- return $this->log($line, self::ALERT);
- }
- /**
- * Writes a $line to the log with a severity level of CRIT.
- *
- * @param string $line Information to log
- * @return void
- */
- public function logCrit($line)
- {
- return $this->log($line, self::CRIT);
- }
- /**
- * Writes a $line to the log with a severity level of EMERG.
- *
- * @param string $line Information to log
- * @return void
- */
- public function logEmerg($line)
- {
- return $this->log($line, self::EMERG);
- }
- /**
- * Writes a $line to the log with the given severity
- *
- * @param string $line Text to add to the log
- * @param integer $severity Severity level of log message (use constants)
- */
- public function log($line, $severity)
- {
-
- if(is_array($line)) {
- $line = var_export($line, true);
- }
-
- if ($this->_severityThreshold >= $severity) {
- $status = $this->_getTimeLine($severity);
- $this->writeFreeFormLine("$status $line \n");
- }
-
- # For when we want to echo the results
- return "$status $line <br>";
-
- }
- /**
- * Writes a line to the log without prepending a status or timestamp
- *
- * @param string $line Line to write to the log
- * @return void
- */
- public function writeFreeFormLine($line)
- {
-
- if ($this->_logStatus == self::STATUS_LOG_OPEN && $this->_severityThreshold != self::OFF) {
- if (fwrite($this->_fileHandle, $line) === false) {
- $this->_messageQueue[] = $this->_messages['writefail'];
- }
- }
-
- }
- private function _getTimeLine($level)
- {
- $time = date(self::$_dateFormat);
- switch ($level) {
- case self::EMERG:
- return "$time - EMERG -->";
- case self::ALERT:
- return "$time - ALERT -->";
- case self::CRIT:
- return "$time - CRIT -->";
- case self::FATAL: # FATAL is an alias of CRIT
- return "$time - FATAL -->";
- case self::NOTICE:
- return "$time - NOTICE -->";
- case self::INFO:
- return "$time - INFO -->";
- case self::WARN:
- return "$time - WARN -->";
- case self::DEBUG:
- return "$time - DEBUG -->";
- case self::ERR:
- return "$time - ERROR -->";
- default:
- return "$time - LOG -->";
- }
- }
- }