diff --git a/src/Logging/MonologErrorHandler.php b/src/Logging/MonologErrorHandler.php index 3b5e7727f..dcb5be1c2 100644 --- a/src/Logging/MonologErrorHandler.php +++ b/src/Logging/MonologErrorHandler.php @@ -2,19 +2,22 @@ namespace SilverStripe\Logging; +use InvalidArgumentException; use Psr\Log\LoggerInterface; use Monolog\ErrorHandler as MonologHandler; class MonologErrorHandler implements ErrorHandler { /** - * @var LoggerInterface + * @var LoggerInterface[] */ - private $logger; + private $loggers = []; /** - * Set the PSR-3 logger to send errors & exceptions to + * Set the PSR-3 logger to send errors & exceptions to. Will overwrite any previously configured + * loggers * + * @deprecated 4.4.0:5.0.0 Use pushHandler() instead * @param LoggerInterface $logger * @return $this */ @@ -25,22 +28,66 @@ class MonologErrorHandler implements ErrorHandler } /** - * Get the PSR-3 logger to send errors & exceptions to + * Get the first registered PSR-3 logger to send errors & exceptions to * + * @deprecated 4.4.0:5.0.0 Use getHandlers() instead * @return LoggerInterface */ public function getLogger() { - return $this->logger; + return reset($this->loggers); } + /** + * Adds a PSR-3 logger to send messages to, to the end of the stack + * + * @param LoggerInterface $logger + * @return $this + */ + public function pushLogger(LoggerInterface $logger) + { + $this->loggers[] = $logger; + return $this; + } + + /** + * Returns the stack of PSR-3 loggers + * + * @return LoggerInterface[] + */ + public function getLoggers() + { + return $this->loggers; + } + + /** + * Set the PSR-3 loggers (overwrites any previously configured values) + * + * @param LoggerInterface[] $loggers + * @return $this + */ + public function setLoggers(array $loggers) + { + $this->loggers = $loggers; + return $this; + } + + /** + * {@inheritDoc} + * + * @throws InvalidArgumentException + */ public function start() { - if (!$this->getLogger()) { - throw new \InvalidArgumentException("No Logger property passed to MonologErrorHandler." - . "Is your Injector config correct?"); + $loggers = $this->getLoggers(); + if (empty($loggers)) { + throw new InvalidArgumentException( + "No Logger properties passed to MonologErrorHandler. Is your Injector config correct?" + ); } - MonologHandler::register($this->getLogger()); + foreach ($loggers as $logger) { + MonologHandler::register($logger); + } } } diff --git a/tests/php/Logging/MonologErrorHandlerTest.php b/tests/php/Logging/MonologErrorHandlerTest.php index c7ec4628e..a7e3159d0 100644 --- a/tests/php/Logging/MonologErrorHandlerTest.php +++ b/tests/php/Logging/MonologErrorHandlerTest.php @@ -2,6 +2,7 @@ namespace SilverStripe\Logging\Tests; +use Psr\Log\LoggerInterface; use SilverStripe\Dev\SapphireTest; use SilverStripe\Logging\MonologErrorHandler; @@ -16,4 +17,20 @@ class MonologErrorHandlerTest extends SapphireTest $handler = new MonologErrorHandler(); $handler->start(); } + + public function testSetLoggerResetsStack() + { + /** @var LoggerInterface $logger */ + $logger = $this->createMock(LoggerInterface::class); + + $handler = new MonologErrorHandler(); + $handler->pushLogger($logger)->pushLogger($logger); + $this->assertCount(2, $handler->getLoggers(), 'Loggers are pushed to the stack'); + + $handler->setLogger($logger); + $this->assertCount(1, $handler->getLoggers(), 'setLogger resets stack and pushes'); + + $handler->setLoggers([]); + $this->assertCount(0, $handler->getLoggers(), 'setLoggers overwrites all configured loggers'); + } }