diff options
Diffstat (limited to 'src/Monolog/ErrorHandler.php')
-rw-r--r-- | src/Monolog/ErrorHandler.php | 86 |
1 files changed, 55 insertions, 31 deletions
diff --git a/src/Monolog/ErrorHandler.php b/src/Monolog/ErrorHandler.php index 7bfcd83..d0b1aa6 100644 --- a/src/Monolog/ErrorHandler.php +++ b/src/Monolog/ErrorHandler.php @@ -1,4 +1,4 @@ -<?php +<?php declare(strict_types=1); /* * This file is part of the Monolog package. @@ -13,7 +13,6 @@ namespace Monolog; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; -use Monolog\Handler\AbstractHandler; /** * Monolog error handler @@ -29,7 +28,7 @@ class ErrorHandler private $logger; private $previousExceptionHandler; - private $uncaughtExceptionLevel; + private $uncaughtExceptionLevelMap; private $previousErrorHandler; private $errorLevelMap; @@ -38,7 +37,7 @@ class ErrorHandler private $hasFatalErrorHandler; private $fatalLevel; private $reservedMemory; - private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR); + private static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR]; public function __construct(LoggerInterface $logger) { @@ -51,12 +50,12 @@ class ErrorHandler * By default it will handle errors, exceptions and fatal errors * * @param LoggerInterface $logger - * @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling - * @param int|false $exceptionLevel a LogLevel::* constant, or false to disable exception handling - * @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling + * @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling + * @param array|false $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling + * @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling * @return ErrorHandler */ - public static function register(LoggerInterface $logger, $errorLevelMap = array(), $exceptionLevel = null, $fatalLevel = null) + public static function register(LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null): self { //Forces the autoloader to run for LogLevel. Fixes an autoload issue at compile-time on PHP5.3. See https://github.com/Seldaek/monolog/pull/929 class_exists('\\Psr\\Log\\LogLevel', true); @@ -65,8 +64,8 @@ class ErrorHandler if ($errorLevelMap !== false) { $handler->registerErrorHandler($errorLevelMap); } - if ($exceptionLevel !== false) { - $handler->registerExceptionHandler($exceptionLevel); + if ($exceptionLevelMap !== false) { + $handler->registerExceptionHandler($exceptionLevelMap); } if ($fatalLevel !== false) { $handler->registerFatalHandler($fatalLevel); @@ -75,38 +74,57 @@ class ErrorHandler return $handler; } - public function registerExceptionHandler($level = null, $callPrevious = true) + public function registerExceptionHandler($levelMap = [], $callPrevious = true): self { - $prev = set_exception_handler(array($this, 'handleException')); - $this->uncaughtExceptionLevel = $level; + $prev = set_exception_handler([$this, 'handleException']); + $this->uncaughtExceptionLevelMap = $levelMap; + foreach ($this->defaultExceptionLevelMap() as $class => $level) { + if (!isset($this->uncaughtExceptionLevelMap[$class])) { + $this->uncaughtExceptionLevelMap[$class] = $level; + } + } if ($callPrevious && $prev) { $this->previousExceptionHandler = $prev; } + + return $this; } - public function registerErrorHandler(array $levelMap = array(), $callPrevious = true, $errorTypes = -1, $handleOnlyReportedErrors = true) + public function registerErrorHandler(array $levelMap = [], $callPrevious = true, $errorTypes = -1, $handleOnlyReportedErrors = true): self { - $prev = set_error_handler(array($this, 'handleError'), $errorTypes); + $prev = set_error_handler([$this, 'handleError'], $errorTypes); $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap); if ($callPrevious) { $this->previousErrorHandler = $prev ?: true; } $this->handleOnlyReportedErrors = $handleOnlyReportedErrors; + + return $this; } - public function registerFatalHandler($level = null, $reservedMemorySize = 20) + public function registerFatalHandler($level = null, $reservedMemorySize = 20): self { - register_shutdown_function(array($this, 'handleFatalError')); + register_shutdown_function([$this, 'handleFatalError']); $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize); $this->fatalLevel = $level; $this->hasFatalErrorHandler = true; + + return $this; + } + + protected function defaultExceptionLevelMap(): array + { + return [ + 'ParseError' => LogLevel::CRITICAL, + 'Throwable' => LogLevel::ERROR, + ]; } - protected function defaultErrorLevelMap() + protected function defaultErrorLevelMap(): array { - return array( + return [ E_ERROR => LogLevel::CRITICAL, E_WARNING => LogLevel::WARNING, E_PARSE => LogLevel::ALERT, @@ -122,7 +140,7 @@ class ErrorHandler E_RECOVERABLE_ERROR => LogLevel::ERROR, E_DEPRECATED => LogLevel::NOTICE, E_USER_DEPRECATED => LogLevel::NOTICE, - ); + ]; } /** @@ -130,10 +148,18 @@ class ErrorHandler */ public function handleException($e) { + $level = LogLevel::ERROR; + foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) { + if ($e instanceof $class) { + $level = $candidate; + break; + } + } + $this->logger->log( - $this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel, + $level, sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()), - array('exception' => $e) + ['exception' => $e] ); if ($this->previousExceptionHandler) { @@ -146,7 +172,7 @@ class ErrorHandler /** * @private */ - public function handleError($code, $message, $file = '', $line = 0, $context = array()) + public function handleError($code, $message, $file = '', $line = 0, $context = []) { if ($this->handleOnlyReportedErrors && !(error_reporting() & $code)) { return; @@ -154,8 +180,8 @@ class ErrorHandler // fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) { - $level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL; - $this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line)); + $level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL; + $this->logger->log($level, self::codeToString($code).': '.$message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]); } if ($this->previousErrorHandler === true) { @@ -170,27 +196,25 @@ class ErrorHandler */ public function handleFatalError() { - $this->reservedMemory = null; + $this->reservedMemory = ''; $lastError = error_get_last(); if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) { $this->logger->log( $this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel, 'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'], - array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line']) + ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line']] ); if ($this->logger instanceof Logger) { foreach ($this->logger->getHandlers() as $handler) { - if ($handler instanceof AbstractHandler) { - $handler->close(); - } + $handler->close(); } } } } - private static function codeToString($code) + private static function codeToString($code): string { switch ($code) { case E_ERROR: |