diff options
Diffstat (limited to 'src/Monolog/Logger.php')
-rw-r--r-- | src/Monolog/Logger.php | 392 |
1 files changed, 114 insertions, 278 deletions
diff --git a/src/Monolog/Logger.php b/src/Monolog/Logger.php index 49d00af..88ecf0d 100644 --- a/src/Monolog/Logger.php +++ b/src/Monolog/Logger.php @@ -1,4 +1,4 @@ -<?php +<?php declare(strict_types=1); /* * This file is part of the Monolog package. @@ -11,8 +11,8 @@ namespace Monolog; +use DateTimeZone; use Monolog\Handler\HandlerInterface; -use Monolog\Handler\StreamHandler; use Psr\Log\LoggerInterface; use Psr\Log\InvalidArgumentException; @@ -84,14 +84,16 @@ class Logger implements LoggerInterface * * @var int */ - const API = 1; + const API = 2; /** * Logging levels from syslog protocol defined in RFC 5424 * - * @var array $levels Logging levels + * This is a static variable and not a constant to serve as an extension point for custom levels + * + * @var string[] $levels Logging levels with the levels as key */ - protected static $levels = array( + protected static $levels = [ self::DEBUG => 'DEBUG', self::INFO => 'INFO', self::NOTICE => 'NOTICE', @@ -100,12 +102,7 @@ class Logger implements LoggerInterface self::CRITICAL => 'CRITICAL', self::ALERT => 'ALERT', self::EMERGENCY => 'EMERGENCY', - ); - - /** - * @var \DateTimeZone - */ - protected static $timezone; + ]; /** * @var string @@ -134,31 +131,33 @@ class Logger implements LoggerInterface protected $microsecondTimestamps = true; /** - * @param string $name The logging channel + * @var DateTimeZone + */ + protected $timezone; + + /** + * @param string $name The logging channel, a simple descriptive name that is attached to all log records * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc. * @param callable[] $processors Optional array of processors + * @param DateTimeZone $timezone Optional timezone, if not provided date_default_timezone_get() will be used */ - public function __construct($name, array $handlers = array(), array $processors = array()) + public function __construct(string $name, array $handlers = [], array $processors = [], DateTimeZone $timezone = null) { $this->name = $name; $this->handlers = $handlers; $this->processors = $processors; + $this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC'); } - /** - * @return string - */ - public function getName() + public function getName(): string { return $this->name; } /** * Return a new cloned instance with the name changed - * - * @return static */ - public function withName($name) + public function withName(string $name): self { $new = clone $this; $new->name = $name; @@ -168,11 +167,8 @@ class Logger implements LoggerInterface /** * Pushes a handler on to the stack. - * - * @param HandlerInterface $handler - * @return $this */ - public function pushHandler(HandlerInterface $handler) + public function pushHandler(HandlerInterface $handler): self { array_unshift($this->handlers, $handler); @@ -182,9 +178,9 @@ class Logger implements LoggerInterface /** * Pops a handler from the stack * - * @return HandlerInterface + * @throws \LogicException If empty handler stack */ - public function popHandler() + public function popHandler(): HandlerInterface { if (!$this->handlers) { throw new \LogicException('You tried to pop from an empty handler stack.'); @@ -198,12 +194,11 @@ class Logger implements LoggerInterface * * If a map is passed, keys will be ignored. * - * @param HandlerInterface[] $handlers - * @return $this + * @param HandlerInterface[] $handlers */ - public function setHandlers(array $handlers) + public function setHandlers(array $handlers): self { - $this->handlers = array(); + $this->handlers = []; foreach (array_reverse($handlers) as $handler) { $this->pushHandler($handler); } @@ -214,22 +209,16 @@ class Logger implements LoggerInterface /** * @return HandlerInterface[] */ - public function getHandlers() + public function getHandlers(): array { return $this->handlers; } /** * Adds a processor on to the stack. - * - * @param callable $callback - * @return $this */ - public function pushProcessor($callback) + public function pushProcessor(callable $callback): self { - if (!is_callable($callback)) { - throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given'); - } array_unshift($this->processors, $callback); return $this; @@ -238,9 +227,10 @@ class Logger implements LoggerInterface /** * Removes the processor on top of the stack and returns it. * + * @throws \LogicException If empty processor stack * @return callable */ - public function popProcessor() + public function popProcessor(): callable { if (!$this->processors) { throw new \LogicException('You tried to pop from an empty processor stack.'); @@ -252,7 +242,7 @@ class Logger implements LoggerInterface /** * @return callable[] */ - public function getProcessors() + public function getProcessors(): array { return $this->processors; } @@ -261,18 +251,22 @@ class Logger implements LoggerInterface * Control the use of microsecond resolution timestamps in the 'datetime' * member of new records. * - * Generating microsecond resolution timestamps by calling + * On PHP7.0, generating microsecond resolution timestamps by calling * microtime(true), formatting the result via sprintf() and then parsing * the resulting string via \DateTime::createFromFormat() can incur * a measurable runtime overhead vs simple usage of DateTime to capture * a second resolution timestamp in systems which generate a large number * of log events. * + * On PHP7.1 however microseconds are always included by the engine, so + * this setting can be left alone unless you really want to suppress + * microseconds in the output. + * * @param bool $micro True to use microtime() to create timestamps */ - public function useMicrosecondTimestamps($micro) + public function useMicrosecondTimestamps(bool $micro) { - $this->microsecondTimestamps = (bool) $micro; + $this->microsecondTimestamps = $micro; } /** @@ -283,56 +277,43 @@ class Logger implements LoggerInterface * @param array $context The log context * @return Boolean Whether the record has been processed */ - public function addRecord($level, $message, array $context = array()) + public function addRecord(int $level, string $message, array $context = []): bool { - if (!$this->handlers) { - $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG)); - } - - $levelName = static::getLevelName($level); - // check if any handler will handle this message so we can return early and save cycles $handlerKey = null; - reset($this->handlers); - while ($handler = current($this->handlers)) { - if ($handler->isHandling(array('level' => $level))) { - $handlerKey = key($this->handlers); + foreach ($this->handlers as $key => $handler) { + if ($handler->isHandling(['level' => $level])) { + $handlerKey = $key; break; } - - next($this->handlers); } if (null === $handlerKey) { return false; } - if (!static::$timezone) { - static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC'); - } - - // php7.1+ always has microseconds enabled, so we do not need this hack - if ($this->microsecondTimestamps && PHP_VERSION_ID < 70100) { - $ts = \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone); - } else { - $ts = new \DateTime(null, static::$timezone); - } - $ts->setTimezone(static::$timezone); + $levelName = static::getLevelName($level); - $record = array( - 'message' => (string) $message, + $record = [ + 'message' => $message, 'context' => $context, 'level' => $level, 'level_name' => $levelName, 'channel' => $this->name, - 'datetime' => $ts, - 'extra' => array(), - ); + 'datetime' => new DateTimeImmutable($this->microsecondTimestamps, $this->timezone), + 'extra' => [], + ]; foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } + // advance the array pointer to the first handler that will handle this record + reset($this->handlers); + while ($handlerKey !== key($this->handlers)) { + next($this->handlers); + } + while ($handler = current($this->handlers)) { if (true === $handler->handle($record)) { break; @@ -345,107 +326,11 @@ class Logger implements LoggerInterface } /** - * Adds a log record at the DEBUG level. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function addDebug($message, array $context = array()) - { - return $this->addRecord(static::DEBUG, $message, $context); - } - - /** - * Adds a log record at the INFO level. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function addInfo($message, array $context = array()) - { - return $this->addRecord(static::INFO, $message, $context); - } - - /** - * Adds a log record at the NOTICE level. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function addNotice($message, array $context = array()) - { - return $this->addRecord(static::NOTICE, $message, $context); - } - - /** - * Adds a log record at the WARNING level. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function addWarning($message, array $context = array()) - { - return $this->addRecord(static::WARNING, $message, $context); - } - - /** - * Adds a log record at the ERROR level. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function addError($message, array $context = array()) - { - return $this->addRecord(static::ERROR, $message, $context); - } - - /** - * Adds a log record at the CRITICAL level. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function addCritical($message, array $context = array()) - { - return $this->addRecord(static::CRITICAL, $message, $context); - } - - /** - * Adds a log record at the ALERT level. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function addAlert($message, array $context = array()) - { - return $this->addRecord(static::ALERT, $message, $context); - } - - /** - * Adds a log record at the EMERGENCY level. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function addEmergency($message, array $context = array()) - { - return $this->addRecord(static::EMERGENCY, $message, $context); - } - - /** * Gets all supported logging levels. * * @return array Assoc array with human-readable level names => level codes. */ - public static function getLevels() + public static function getLevels(): array { return array_flip(static::$levels); } @@ -453,10 +338,11 @@ class Logger implements LoggerInterface /** * Gets the name of the logging level. * - * @param int $level + * @param int $level + * @throws \Psr\Log\InvalidArgumentException If level is not defined * @return string */ - public static function getLevelName($level) + public static function getLevelName(int $level): string { if (!isset(static::$levels[$level])) { throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels))); @@ -469,12 +355,17 @@ class Logger implements LoggerInterface * Converts PSR-3 levels to Monolog ones if necessary * * @param string|int Level number (monolog) or name (PSR-3) + * @throws \Psr\Log\InvalidArgumentException If level is not defined * @return int */ - public static function toMonologLevel($level) + public static function toMonologLevel($level): int { - if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) { - return constant(__CLASS__.'::'.strtoupper($level)); + if (is_string($level)) { + if (defined(__CLASS__.'::'.strtoupper($level))) { + return constant(__CLASS__.'::'.strtoupper($level)); + } + + throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels))); } return $level; @@ -486,11 +377,11 @@ class Logger implements LoggerInterface * @param int $level * @return Boolean */ - public function isHandling($level) + public function isHandling(int $level): bool { - $record = array( + $record = [ 'level' => $level, - ); + ]; foreach ($this->handlers as $handler) { if ($handler->isHandling($record)) { @@ -506,16 +397,15 @@ class Logger implements LoggerInterface * * This method allows for compatibility with common interfaces. * - * @param mixed $level The log level - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param mixed $level The log level + * @param string $message The log message + * @param array $context The log context */ - public function log($level, $message, array $context = array()) + public function log($level, $message, array $context = []) { $level = static::toMonologLevel($level); - return $this->addRecord($level, $message, $context); + $this->addRecord($level, (string) $message, $context); } /** @@ -523,13 +413,12 @@ class Logger implements LoggerInterface * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context */ - public function debug($message, array $context = array()) + public function debug($message, array $context = []) { - return $this->addRecord(static::DEBUG, $message, $context); + $this->addRecord(static::DEBUG, (string) $message, $context); } /** @@ -537,13 +426,12 @@ class Logger implements LoggerInterface * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context */ - public function info($message, array $context = array()) + public function info($message, array $context = []) { - return $this->addRecord(static::INFO, $message, $context); + $this->addRecord(static::INFO, (string) $message, $context); } /** @@ -551,13 +439,12 @@ class Logger implements LoggerInterface * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context */ - public function notice($message, array $context = array()) + public function notice($message, array $context = []) { - return $this->addRecord(static::NOTICE, $message, $context); + $this->addRecord(static::NOTICE, (string) $message, $context); } /** @@ -565,41 +452,12 @@ class Logger implements LoggerInterface * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function warn($message, array $context = array()) - { - return $this->addRecord(static::WARNING, $message, $context); - } - - /** - * Adds a log record at the WARNING level. - * - * This method allows for compatibility with common interfaces. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function warning($message, array $context = array()) - { - return $this->addRecord(static::WARNING, $message, $context); - } - - /** - * Adds a log record at the ERROR level. - * - * This method allows for compatibility with common interfaces. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context */ - public function err($message, array $context = array()) + public function warning($message, array $context = []) { - return $this->addRecord(static::ERROR, $message, $context); + $this->addRecord(static::WARNING, (string) $message, $context); } /** @@ -607,13 +465,12 @@ class Logger implements LoggerInterface * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context */ - public function error($message, array $context = array()) + public function error($message, array $context = []) { - return $this->addRecord(static::ERROR, $message, $context); + $this->addRecord(static::ERROR, (string) $message, $context); } /** @@ -621,27 +478,12 @@ class Logger implements LoggerInterface * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context */ - public function crit($message, array $context = array()) + public function critical($message, array $context = []) { - return $this->addRecord(static::CRITICAL, $message, $context); - } - - /** - * Adds a log record at the CRITICAL level. - * - * This method allows for compatibility with common interfaces. - * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed - */ - public function critical($message, array $context = array()) - { - return $this->addRecord(static::CRITICAL, $message, $context); + $this->addRecord(static::CRITICAL, (string) $message, $context); } /** @@ -649,13 +491,12 @@ class Logger implements LoggerInterface * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context */ - public function alert($message, array $context = array()) + public function alert($message, array $context = []) { - return $this->addRecord(static::ALERT, $message, $context); + $this->addRecord(static::ALERT, (string) $message, $context); } /** @@ -663,38 +504,33 @@ class Logger implements LoggerInterface * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context */ - public function emerg($message, array $context = array()) + public function emergency($message, array $context = []) { - return $this->addRecord(static::EMERGENCY, $message, $context); + $this->addRecord(static::EMERGENCY, (string) $message, $context); } /** - * Adds a log record at the EMERGENCY level. - * - * This method allows for compatibility with common interfaces. + * Set the timezone to be used for the timestamp of log records. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param DateTimeZone $tz Timezone object */ - public function emergency($message, array $context = array()) + public function setTimezone(DateTimeZone $tz): self { - return $this->addRecord(static::EMERGENCY, $message, $context); + $this->timezone = $tz; + + return $this; } /** * Set the timezone to be used for the timestamp of log records. * - * This is stored globally for all Logger instances - * - * @param \DateTimeZone $tz Timezone object + * @return DateTimeZone */ - public static function setTimezone(\DateTimeZone $tz) + public function getTimezone(): DateTimeZone { - self::$timezone = $tz; + return $this->timezone; } } |