diff options
author | Benaka Moorthi <benaka.moorthi@gmail.com> | 2013-09-23 12:05:13 +0400 |
---|---|---|
committer | Benaka Moorthi <benaka.moorthi@gmail.com> | 2013-09-23 12:05:13 +0400 |
commit | 809ca913e379113e4c64e9fa82a0d8f17fe8fca6 (patch) | |
tree | 0d6eb5c1d02430df4a260371135e392068994261 /core/Log.php | |
parent | 6dce0122d24c3b2f7b07c26a69c850f86075e025 (diff) |
Initial refactoring.
Diffstat (limited to 'core/Log.php')
-rw-r--r-- | core/Log.php | 386 |
1 files changed, 245 insertions, 141 deletions
diff --git a/core/Log.php b/core/Log.php index a2720098dd..feeaf92ef4 100644 --- a/core/Log.php +++ b/core/Log.php @@ -10,196 +10,300 @@ */ namespace Piwik; -use Piwik\Log\APICall; -use Piwik\Log\Error; -use Piwik\Log\Exception; -use Piwik\Log\Message; +use Piwik\Common; +use Piwik\Db; + +/* TODO: +; all calls to the API (method name, parameters, execution time, caller IP, etc.) +; disabled by default as it can cause serious overhead and should only be used wisely +;logger_api_call[] = file +*/ /** - * - * @package Piwik - * @subpackage Log - * @see Zend_Log, libs/Zend/Log.php - * @link http://framework.zend.com/manual/en/zend.log.html + * TODO */ -abstract class Log extends \Zend_Log +class Log { - protected $logToDatabaseTableName = null; - protected $logToDatabaseColumnMapping = null; - protected $logToFileFilename = null; - protected $fileFormatter = null; - protected $screenFormatter = null; - protected $currentRequestKey; + // log levels + const NONE = 0; + const ERROR = 1; + const WARN = 2; + const INFO = 3; + const DEBUG = 4; + const VERBOSE = 5; + + // config option names + const LOG_LEVEL_CONFIG_OPTION = 'log_level'; + const LOG_WRITERS_CONFIG_OPTION = 'log_writers'; + const LOGGER_FILE_PATH_CONFIG_OPTION = 'logger_file_path'; + const LOGGER_DATABASE_TABLE_CONFIG_OPTION = 'logger_db_table'; + + /** + * TODO + */ + private static $instance = null; + + /** + * TODO + */ + public static function getInstance() + { + if (self::$instance === null) { + self::$instance = new Log(); + } + return self::$instance; + } + + /** + * TODO + */ + private $currentLogLevel = self::WARN; + + /** + * TODO + */ + private $writers = array(); + + /** + * TODO + */ + private $logMessageFormat = "[%pluginName%:%datetime%] %message%"; + + /** + * TODO + */ + private $logToDatabaseTable = "logger_message"; + + /** + * TODO + */ + private $logToFileFilename; /** - * @param string $logToFileFilename filename of logfile - * @param \Zend_Log_Formatter_Interface $fileFormatter - * @param \Zend_Log_Formatter_Interface $screenFormatter - * @param string $logToDatabaseTableName - * @param array $logToDatabaseColumnMapping + * TODO */ - function __construct($logToFileFilename, - $fileFormatter, - $screenFormatter, - $logToDatabaseTableName, - $logToDatabaseColumnMapping) + public function __construct() { - parent::__construct(); + $logConfig = Config::getInstance()->log; + $this->setCurrentLogLevelFromConfig($logConfig); + $this->setLogWritersFromConfig($logConfig); + $this->setLogFilePathFromConfig($logConfig); + $this->setLogDatabaseTableFromConfig($logConfig); + $this->disableLoggingBasedOnConfig($logConfig); + } - $this->currentRequestKey = substr(Common::generateUniqId(), 0, 8); + private function setLogWritersFromConfig($logConfig) + { + // set the log writers + $logWriters = $logConfig[self::LOG_WRITERS_CONFIG_OPTION]; - $log_dir = Config::getInstance()->log['logger_file_path']; - if ($log_dir[0] != '/' && $log_dir[0] != DIRECTORY_SEPARATOR) { - $log_dir = PIWIK_USER_PATH . '/' . $log_dir; + $logWriters = array_map('trim', $logWriters); + foreach ($logWriters as $writerName) { + $writer = $this->createWriterByName($writerName); + if (!empty($writer)) { + $this->writers[] = $writer; + } } - $this->logToFileFilename = $log_dir . '/' . $logToFileFilename; + } + + private function setCurrentLogLevelFromConfig($logConfig) + { + if (!empty($logConfig[self::LOG_LEVEL_CONFIG_OPTION])) { + $logLevel = $this->getLogLevelFromStringName(self::LOG_LEVEL_CONFIG_OPTION); - $this->fileFormatter = $fileFormatter; - $this->screenFormatter = $screenFormatter; - $this->logToDatabaseTableName = Common::prefixTable($logToDatabaseTableName); - $this->logToDatabaseColumnMapping = $logToDatabaseColumnMapping; + if ($logLevel >= self::NONE // sanity check + && $logLevel <= self::VERBOSE + ) { + $this->currentLogLevel = $logLevel; + } + } } - function addWriteToFile() + private function setLogDatabaseTableFromConfig($logConfig) { - Filesystem::mkdir(dirname($this->logToFileFilename)); - $writerFile = new \Zend_Log_Writer_Stream($this->logToFileFilename); - $writerFile->setFormatter($this->fileFormatter); - $this->addWriter($writerFile); + if (!empty($logConfig[self::LOGGER_DATABASE_TABLE_CONFIG_OPTION])) { + $this->logToDatabaseTable = $logConfig[self::LOGGER_DATABASE_TABLE_CONFIG_OPTION]; + } } - function addWriteToNull() + private function setLogFilePathFromConfig($logConfig) { - $this->addWriter(new \Zend_Log_Writer_Null); + $logDir = $logConfig[self::LOGGER_FILE_PATH_CONFIG_OPTION]; + if ($logDir[0] != '/' && $logDir[0] != DIRECTORY_SEPARATOR) { + $logDir = PIWIK_USER_PATH . '/' . $logDir; + } + $this->logToFileFilename = $logDir . '/piwik.log'; } - function addWriteToDatabase() + private function createWriterByName($writerName) { - $writerDb = new \Zend_Log_Writer_Db( - \Zend_Registry::get('db'), - $this->logToDatabaseTableName, - $this->logToDatabaseColumnMapping); + $self = $this; + + $writer = false; + if ($writerName == 'file') { + $writer = function ($pluginName, $datetime, $message) use ($self) { + $self->logToFile($this->formatMessage($pluginName, $datetime, $message)); + }; + } else if ($writerName == 'screen') { + $writer = function ($pluginName, $datetime, $message) use ($self) { + $self->logToScreen($this->formatMessage($pluginName, $datetime, $message)); + }; + } else if ($writerName == 'db') { + $writer = function ($pluginName, $datetime, $message) use ($self) { + $self->logToDatabase($pluginName, $datetime, $message); + }; + } + return $writer; + } - $this->addWriter($writerDb); + private function logToFile($message) + { + file_put_contents($this->logToFileFilename, $message . "\n", FILE_APPEND); } - function addWriteToScreen() + private function logToScreen($message) { - $writerScreen = new \Zend_Log_Writer_Stream('php://output'); - $writerScreen->setFormatter($this->screenFormatter); - $this->addWriter($writerScreen); + echo $message . "\n"; } - public function getWritersCount() + private function logToDatabase($pluginName, $datetime, $message) { - return count($this->_writers); + $sql = "INSERT INTO " . Common::prefixTable($this->logToDatabaseTable) + . " (plugin, time, message)" + . " VALUES (?, ?, ?)"; + Db::query($sql, array($pluginName, $datetime, $message)); } /** - * Log an event - * @param string $event - * @param int $priority - * @param null $extras - * @throws \Zend_Log_Exception - * @return void + * TODO */ - public function log($event, $priority, $extras = null) + public function log($level, $pluginName, $message, $sprintfParams = array()) { - // sanity checks - if (empty($this->_writers)) { - throw new \Zend_Log_Exception('No writers were added'); + if ($this->shouldLoggerLog($level)) { + $datetime = date("Y-m-d H:i:s"); + $message = sprintf($message, $sprintfParams); + + $this->writeMessage($pluginName, $message, $datetime); } + } - $event['timestamp'] = date('Y-m-d H:i:s'); - $event['requestKey'] = $this->currentRequestKey; - // pack into event required by filters and writers - $event = array_merge($event, $this->_extras); + /** + * TODO + */ + private function formatMessage($pluginName, $message, $datetime) + { + return str_replace( + array("%pluginName%", "%message%", "%datetime%"), + array($pluginName, $message, $datetime), + $this->logMessageFormat + ); + } - // one message must stay on one line - if (isset($event['message'])) { - $event['message'] = str_replace(array(PHP_EOL, "\n"), " ", $event['message']); + /** + * TODO + */ + private function writeMessage($pluginName, $datetime, $message) + { + foreach ($this->writers as $writer) { + $writer($pluginName, $datetime, $message); } + } - // Truncate the backtrace which can be too long to display in the browser - if (!empty($event['backtrace'])) { - $maxSizeOutputBytes = 1024 * 1024; // no more than 1M output please - $truncateBacktraceLineAfter = 1000; - $maxLines = ceil($maxSizeOutputBytes / $truncateBacktraceLineAfter); - $bt = explode("\n", $event['backtrace']); - foreach ($bt as $count => &$line) { - if (strlen($line) > $truncateBacktraceLineAfter) { - $line = substr($line, 0, $truncateBacktraceLineAfter) . '...'; - } - if ($count > $maxLines) { - $line .= "\nTruncated error message."; - break; - } - } - $event['backtrace'] = implode("\n", $bt); - } - // abort if rejected by the global filters - foreach ($this->_filters as $filter) { - if (!$filter->accept($event)) { - return; - } - } + /** + * TODO + */ + public static function log($level, $pluginName, $message, $sprintfParams = array()) + { + self::getInstance()->log($level, $pluginName, $message, $sprintfParams); + } - // send to each writer - foreach ($this->_writers as $writer) { - $writer->write($event); - } + /** + * TODO + */ + public static function e($pluginName, $message, $sprintfParams = array()) + { + self::log(self::ERROR, $pluginName, $message, $sprintfParams); } + /** + * TODO + */ + public static function w($pluginName, $message, $sprintfParams = array()) + { + self::log(self::WARN, $pluginName, $message, $sprintfParams); + } /** - * Create log object - * @throws Exception + * TODO */ - static public function make() + public static function i($pluginName, $message, $sprintfParams = array()) { - $configAPI = Config::getInstance()->log; + self::log(self::INFO, $pluginName, $message, $sprintfParams); + } - /** @var Log[] $aLoggers */ - $aLoggers = array( - 'logger_api_call' => new APICall, - 'logger_exception' => new Exception, - 'logger_error' => new Error, - 'logger_message' => new Message, - ); + /** + * TODO + */ + public static function d($pluginName, $message, $sprintfParams = array()) + { + self::log(self::DEBUG, $pluginName, $message, $sprintfParams); + } - foreach ($configAPI as $loggerType => $aRecordTo) { - if (isset($aLoggers[$loggerType])) { - $logger = $aLoggers[$loggerType]; - - foreach ($aRecordTo as $recordTo) { - switch ($recordTo) { - case 'screen': - $logger->addWriteToScreen(); - break; - - case 'database': - $logger->addWriteToDatabase(); - break; - - case 'file': - $logger->addWriteToFile(); - break; - - default: - throw new \Exception("'$recordTo' is not a valid Log type. Valid logger types are: screen, database, file."); - break; - } - } - } + /** + * TODO + */ + public static function v($pluginName, $message, $sprintfParams = array()) + { + self::log(self::VERBOSE, $pluginName, $message, $sprintfParams); + } + + /** + * Returns if logging should work + * @return bool + */ + private function shouldLoggerLog($level) + { + return $level <= $this->currentLogLevel; + } + + private function disableLoggingBasedOnConfig($logConfig) + { + $disableLogging = false; + + if (!empty($logConfig['log_only_when_cli']) + && !Common::isPhpCliMode() + ) { + $disableLogging = true; } - foreach ($aLoggers as $loggerType => $logger) { - if ($logger->getWritersCount() == 0) { - $logger->addWriteToNull(); - } - \Zend_Registry::set($loggerType, $logger); + if (!empty($logConfig['log_only_when_debug_parameter']) + && !isset($_REQUEST['debug']) + ) { + $disableLogging = true; } - } -} + if ($disableLogging) { + $this->currentLogLevel = self::NONE; + } + } + private function getLogLevelFromStringName($name) + { + switch ($name) { + case 'NONE': + return self::NONE; + case 'ERROR': + return self::ERROR; + case 'WARN': + return self::WARN; + case 'INFO': + return self::INFO; + case 'DEBUG': + return self::DEBUG; + case 'VERBOSE': + return self::VERBOSE; + default: + return -1; + } + } +}
\ No newline at end of file |