Source of file Logger.php
Size: 20,561 Bytes - Last Modified: 2014-03-12T23:21:18+01:00
/home/theseer/Downloads/ZendFramework-2.3.0/library/Zend/Log/Logger.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697 | <?php /** * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\Log; use DateTime; use ErrorException; use Traversable; use Zend\ServiceManager\AbstractPluginManager; use Zend\Stdlib\ArrayUtils; use Zend\Stdlib\SplPriorityQueue; /** * Logging messages with a stack of backends */ class Logger implements LoggerInterface { /** * @const int defined from the BSD Syslog message severities * @link http://tools.ietf.org/html/rfc3164 */ const EMERG = 0; const ALERT = 1; const CRIT = 2; const ERR = 3; const WARN = 4; const NOTICE = 5; const INFO = 6; const DEBUG = 7; /** * Map native PHP errors to priority * * @var array */ public static $errorPriorityMap = array( E_NOTICE => self::NOTICE, E_USER_NOTICE => self::NOTICE, E_WARNING => self::WARN, E_CORE_WARNING => self::WARN, E_USER_WARNING => self::WARN, E_ERROR => self::ERR, E_USER_ERROR => self::ERR, E_CORE_ERROR => self::ERR, E_RECOVERABLE_ERROR => self::ERR, E_STRICT => self::DEBUG, E_DEPRECATED => self::DEBUG, E_USER_DEPRECATED => self::DEBUG, ); /** * Registered error handler * * @var bool */ protected static $registeredErrorHandler = false; /** * Registered shutdown error handler * * @var bool */ protected static $registeredFatalErrorShutdownFunction = false; /** * Registered exception handler * * @var bool */ protected static $registeredExceptionHandler = false; /** * List of priority code => priority (short) name * * @var array */ protected $priorities = array( self::EMERG => 'EMERG', self::ALERT => 'ALERT', self::CRIT => 'CRIT', self::ERR => 'ERR', self::WARN => 'WARN', self::NOTICE => 'NOTICE', self::INFO => 'INFO', self::DEBUG => 'DEBUG', ); /** * Writers * * @var SplPriorityQueue */ protected $writers; /** * Processors * * @var SplPriorityQueue */ protected $processors; /** * Writer plugins * * @var WriterPluginManager */ protected $writerPlugins; /** * Processor plugins * * @var ProcessorPluginManager */ protected $processorPlugins; /** * Constructor * * Set options for a logger. Accepted options are: * - writers: array of writers to add to this logger * - exceptionhandler: if true register this logger as exceptionhandler * - errorhandler: if true register this logger as errorhandler * * @param array|Traversable $options * @return Logger * @throws Exception\InvalidArgumentException */ public function __construct($options = null) { $this->writers = new SplPriorityQueue(); $this->processors = new SplPriorityQueue(); if ($options instanceof Traversable) { $options = ArrayUtils::iteratorToArray($options); } if (!$options) { return; } if (!is_array($options)) { throw new Exception\InvalidArgumentException('Options must be an array or an object implementing \Traversable '); } // Inject writer plugin manager, if available if (isset($options['writer_plugin_manager']) && $options['writer_plugin_manager'] instanceof AbstractPluginManager ) { $this->setWriterPluginManager($options['writer_plugin_manager']); } // Inject processor plugin manager, if available if (isset($options['processor_plugin_manager']) && $options['processor_plugin_manager'] instanceof AbstractPluginManager ) { $this->setProcessorPluginManager($options['processor_plugin_manager']); } if (isset($options['writers']) && is_array($options['writers'])) { foreach ($options['writers'] as $writer) { if (!isset($writer['name'])) { throw new Exception\InvalidArgumentException('Options must contain a name for the writer'); } $priority = (isset($writer['priority'])) ? $writer['priority'] : null; $writerOptions = (isset($writer['options'])) ? $writer['options'] : null; $this->addWriter($writer['name'], $priority, $writerOptions); } } if (isset($options['processors']) && is_array($options['processors'])) { foreach ($options['processors'] as $processor) { if (!isset($processor['name'])) { throw new Exception\InvalidArgumentException('Options must contain a name for the processor'); } $priority = (isset($processor['priority'])) ? $processor['priority'] : null; $processorOptions = (isset($processor['options'])) ? $processor['options'] : null; $this->addProcessor($processor['name'], $priority, $processorOptions); } } if (isset($options['exceptionhandler']) && $options['exceptionhandler'] === true) { static::registerExceptionHandler($this); } if (isset($options['errorhandler']) && $options['errorhandler'] === true) { static::registerErrorHandler($this); } if (isset($options['fatal_error_shutdownfunction']) && $options['fatal_error_shutdownfunction'] === true) { static::registerFatalErrorShutdownFunction($this); } } /** * Shutdown all writers * * @return void */ public function __destruct() { foreach ($this->writers as $writer) { try { $writer->shutdown(); } catch (\Exception $e) {} } } /** * Get writer plugin manager * * @return WriterPluginManager */ public function getWriterPluginManager() { if (null === $this->writerPlugins) { $this->setWriterPluginManager(new WriterPluginManager()); } return $this->writerPlugins; } /** * Set writer plugin manager * * @param string|WriterPluginManager $plugins * @return Logger * @throws Exception\InvalidArgumentException */ public function setWriterPluginManager($plugins) { if (is_string($plugins)) { $plugins = new $plugins; } if (!$plugins instanceof WriterPluginManager) { throw new Exception\InvalidArgumentException(sprintf( 'Writer plugin manager must extend %s\WriterPluginManager; received %s', __NAMESPACE__, is_object($plugins) ? get_class($plugins) : gettype($plugins) )); } $this->writerPlugins = $plugins; return $this; } /** * Get writer instance * * @param string $name * @param array|null $options * @return Writer\WriterInterface */ public function writerPlugin($name, array $options = null) { return $this->getWriterPluginManager()->get($name, $options); } /** * Add a writer to a logger * * @param string|Writer\WriterInterface $writer * @param int $priority * @param array|null $options * @return Logger * @throws Exception\InvalidArgumentException */ public function addWriter($writer, $priority = 1, array $options = null) { if (is_string($writer)) { $writer = $this->writerPlugin($writer, $options); } elseif (!$writer instanceof Writer\WriterInterface) { throw new Exception\InvalidArgumentException(sprintf( 'Writer must implement %s\Writer\WriterInterface; received "%s"', __NAMESPACE__, is_object($writer) ? get_class($writer) : gettype($writer) )); } $this->writers->insert($writer, $priority); return $this; } /** * Get writers * * @return SplPriorityQueue */ public function getWriters() { return $this->writers; } /** * Set the writers * * @param SplPriorityQueue $writers * @return Logger * @throws Exception\InvalidArgumentException */ public function setWriters(SplPriorityQueue $writers) { foreach ($writers->toArray() as $writer) { if (!$writer instanceof Writer\WriterInterface) { throw new Exception\InvalidArgumentException('Writers must be a SplPriorityQueue of Zend\Log\Writer'); } } $this->writers = $writers; return $this; } /** * Get processor plugin manager * * @return ProcessorPluginManager */ public function getProcessorPluginManager() { if (null === $this->processorPlugins) { $this->setProcessorPluginManager(new ProcessorPluginManager()); } return $this->processorPlugins; } /** * Set processor plugin manager * * @param string|ProcessorPluginManager $plugins * @return Logger * @throws Exception\InvalidArgumentException */ public function setProcessorPluginManager($plugins) { if (is_string($plugins)) { $plugins = new $plugins; } if (!$plugins instanceof ProcessorPluginManager) { throw new Exception\InvalidArgumentException(sprintf( 'processor plugin manager must extend %s\ProcessorPluginManager; received %s', __NAMESPACE__, is_object($plugins) ? get_class($plugins) : gettype($plugins) )); } $this->processorPlugins = $plugins; return $this; } /** * Get processor instance * * @param string $name * @param array|null $options * @return Processor\ProcessorInterface */ public function processorPlugin($name, array $options = null) { return $this->getProcessorPluginManager()->get($name, $options); } /** * Add a processor to a logger * * @param string|Processor\ProcessorInterface $processor * @param int $priority * @param array|null $options * @return Logger * @throws Exception\InvalidArgumentException */ public function addProcessor($processor, $priority = 1, array $options = null) { if (is_string($processor)) { $processor = $this->processorPlugin($processor, $options); } elseif (!$processor instanceof Processor\ProcessorInterface) { throw new Exception\InvalidArgumentException(sprintf( 'Processor must implement Zend\Log\ProcessorInterface; received "%s"', is_object($processor) ? get_class($processor) : gettype($processor) )); } $this->processors->insert($processor, $priority); return $this; } /** * Get processors * * @return SplPriorityQueue */ public function getProcessors() { return $this->processors; } /** * Add a message as a log entry * * @param int $priority * @param mixed $message * @param array|Traversable $extra * @return Logger * @throws Exception\InvalidArgumentException if message can't be cast to string * @throws Exception\InvalidArgumentException if extra can't be iterated over * @throws Exception\RuntimeException if no log writer specified */ public function log($priority, $message, $extra = array()) { if (!is_int($priority) || ($priority<0) || ($priority>=count($this->priorities))) { throw new Exception\InvalidArgumentException(sprintf( '$priority must be an integer > 0 and < %d; received %s', count($this->priorities), var_export($priority, 1) )); } if (is_object($message) && !method_exists($message, '__toString')) { throw new Exception\InvalidArgumentException( '$message must implement magic __toString() method' ); } if (!is_array($extra) && !$extra instanceof Traversable) { throw new Exception\InvalidArgumentException( '$extra must be an array or implement Traversable' ); } elseif ($extra instanceof Traversable) { $extra = ArrayUtils::iteratorToArray($extra); } if ($this->writers->count() === 0) { throw new Exception\RuntimeException('No log writer specified'); } $timestamp = new DateTime(); if (is_array($message)) { $message = var_export($message, true); } $event = array( 'timestamp' => $timestamp, 'priority' => (int) $priority, 'priorityName' => $this->priorities[$priority], 'message' => (string) $message, 'extra' => $extra ); foreach ($this->processors->toArray() as $processor) { $event = $processor->process($event); } foreach ($this->writers->toArray() as $writer) { $writer->write($event); } return $this; } /** * @param string $message * @param array|Traversable $extra * @return Logger */ public function emerg($message, $extra = array()) { return $this->log(self::EMERG, $message, $extra); } /** * @param string $message * @param array|Traversable $extra * @return Logger */ public function alert($message, $extra = array()) { return $this->log(self::ALERT, $message, $extra); } /** * @param string $message * @param array|Traversable $extra * @return Logger */ public function crit($message, $extra = array()) { return $this->log(self::CRIT, $message, $extra); } /** * @param string $message * @param array|Traversable $extra * @return Logger */ public function err($message, $extra = array()) { return $this->log(self::ERR, $message, $extra); } /** * @param string $message * @param array|Traversable $extra * @return Logger */ public function warn($message, $extra = array()) { return $this->log(self::WARN, $message, $extra); } /** * @param string $message * @param array|Traversable $extra * @return Logger */ public function notice($message, $extra = array()) { return $this->log(self::NOTICE, $message, $extra); } /** * @param string $message * @param array|Traversable $extra * @return Logger */ public function info($message, $extra = array()) { return $this->log(self::INFO, $message, $extra); } /** * @param string $message * @param array|Traversable $extra * @return Logger */ public function debug($message, $extra = array()) { return $this->log(self::DEBUG, $message, $extra); } /** * Register logging system as an error handler to log PHP errors * * @link http://www.php.net/manual/function.set-error-handler.php * @param Logger $logger * @param bool $continueNativeHandler * @return mixed Returns result of set_error_handler * @throws Exception\InvalidArgumentException if logger is null */ public static function registerErrorHandler(Logger $logger, $continueNativeHandler = false) { // Only register once per instance if (static::$registeredErrorHandler) { return false; } $errorPriorityMap = static::$errorPriorityMap; $previous = set_error_handler(function ($level, $message, $file, $line) use ($logger, $errorPriorityMap, $continueNativeHandler) { $iniLevel = error_reporting(); if ($iniLevel & $level) { if (isset($errorPriorityMap[$level])) { $priority = $errorPriorityMap[$level]; } else { $priority = Logger::INFO; } $logger->log($priority, $message, array( 'errno' => $level, 'file' => $file, 'line' => $line, )); } return !$continueNativeHandler; }); static::$registeredErrorHandler = true; return $previous; } /** * Unregister error handler * */ public static function unregisterErrorHandler() { restore_error_handler(); static::$registeredErrorHandler = false; } /** * Register a shutdown handler to log fatal errors * * @link http://www.php.net/manual/function.register-shutdown-function.php * @param Logger $logger * @return bool */ public static function registerFatalErrorShutdownFunction(Logger $logger) { // Only register once per instance if (static::$registeredFatalErrorShutdownFunction) { return false; } $errorPriorityMap = static::$errorPriorityMap; register_shutdown_function(function () use ($logger, $errorPriorityMap) { $error = error_get_last(); if (null !== $error && $error['type'] === E_ERROR) { $logger->log($errorPriorityMap[E_ERROR], $error['message'], array( 'file' => $error['file'], 'line' => $error['line'] ) ); } }); static::$registeredFatalErrorShutdownFunction = true; return true; } /** * Register logging system as an exception handler to log PHP exceptions * * @link http://www.php.net/manual/en/function.set-exception-handler.php * @param Logger $logger * @return bool * @throws Exception\InvalidArgumentException if logger is null */ public static function registerExceptionHandler(Logger $logger) { // Only register once per instance if (static::$registeredExceptionHandler) { return false; } if ($logger === null) { throw new Exception\InvalidArgumentException('Invalid Logger specified'); } $errorPriorityMap = static::$errorPriorityMap; set_exception_handler(function ($exception) use ($logger, $errorPriorityMap) { $logMessages = array(); do { $priority = Logger::ERR; if ($exception instanceof ErrorException && isset($errorPriorityMap[$exception->getSeverity()])) { $priority = $errorPriorityMap[$exception->getSeverity()]; } $extra = array( 'file' => $exception->getFile(), 'line' => $exception->getLine(), 'trace' => $exception->getTrace(), ); if (isset($exception->xdebug_message)) { $extra['xdebug'] = $exception->xdebug_message; } $logMessages[] = array( 'priority' => $priority, 'message' => $exception->getMessage(), 'extra' => $extra, ); $exception = $exception->getPrevious(); } while ($exception); foreach (array_reverse($logMessages) as $logMessage) { $logger->log($logMessage['priority'], $logMessage['message'], $logMessage['extra']); } }); static::$registeredExceptionHandler = true; return true; } /** * Unregister exception handler */ public static function unregisterExceptionHandler() { restore_exception_handler(); static::$registeredExceptionHandler = false; } } |