From 7913cd2c4d0f97c8903c1c00413621128aa409da Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 11 Dec 2012 11:15:54 +0100 Subject: [PATCH] Add psr/log compatibility --- composer.json | 3 +- src/Monolog/Logger.php | 82 ++++++++++++++++++- .../Processor/PsrLogMessageProcessor.php | 42 ++++++++++ tests/Monolog/PsrLogCompatTest.php | 47 +++++++++++ 4 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 src/Monolog/Processor/PsrLogMessageProcessor.php create mode 100644 tests/Monolog/PsrLogCompatTest.php diff --git a/composer.json b/composer.json index 9db9073a..3103ca2b 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ } ], "require": { - "php": ">=5.3.0" + "php": ">=5.3.0", + "psr/log": "~1.0" }, "require-dev": { "mlehner/gelf-php": "1.0.*" diff --git a/src/Monolog/Logger.php b/src/Monolog/Logger.php index d7b89005..9c6adcb7 100644 --- a/src/Monolog/Logger.php +++ b/src/Monolog/Logger.php @@ -13,6 +13,8 @@ namespace Monolog; use Monolog\Handler\HandlerInterface; use Monolog\Handler\StreamHandler; +use Psr\Log\LoggerInterface; +use Psr\Log\InvalidArgumentException; /** * Monolog log channel @@ -22,7 +24,7 @@ use Monolog\Handler\StreamHandler; * * @author Jordi Boggiano */ -class Logger +class Logger implements LoggerInterface { /** * Detailed debug information @@ -206,6 +208,7 @@ class Logger if (null === $handlerKey) { return false; } + // found at least one, process message and dispatch it foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); @@ -323,7 +326,7 @@ class Logger public static function getLevelName($level) { if (!isset(static::$levels[$level])) { - throw new \InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels))); + throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels))); } return static::$levels[$level]; @@ -350,6 +353,25 @@ class Logger return false; } + /** + * Adds a log record at an arbitrary level. + * + * 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 + */ + public function log($level, $message, array $context = array()) + { + if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) { + $level = constant(__CLASS__.'::'.strtoupper($level)); + } + + return $this->addRecord($level, $message, $context); + } + /** * Adds a log record at the DEBUG level. * @@ -406,6 +428,20 @@ class Logger 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. * @@ -420,6 +456,20 @@ class Logger return $this->addRecord(static::ERROR, $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 + */ + public function error($message, array $context = array()) + { + return $this->addRecord(static::ERROR, $message, $context); + } + /** * Adds a log record at the CRITICAL level. * @@ -434,6 +484,20 @@ class Logger 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); + } + /** * Adds a log record at the ALERT level. * @@ -461,4 +525,18 @@ class Logger { return $this->addRecord(static::EMERGENCY, $message, $context); } + + /** + * Adds a log record at the EMERGENCY 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 emergency($message, array $context = array()) + { + return $this->addRecord(static::EMERGENCY, $message, $context); + } } diff --git a/src/Monolog/Processor/PsrLogMessageProcessor.php b/src/Monolog/Processor/PsrLogMessageProcessor.php new file mode 100644 index 00000000..b63fcccc --- /dev/null +++ b/src/Monolog/Processor/PsrLogMessageProcessor.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +/** + * Processes a record's message according to PSR-3 rules + * + * It replaces {foo} with the value from $context['foo'] + * + * @author Jordi Boggiano + */ +class PsrLogMessageProcessor +{ + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + if (false === strpos($record['message'], '{')) { + return $record; + } + + $replacements = array(); + foreach ($record['context'] as $key => $val) { + $replacements['{'.$key.'}'] = $val; + } + + $record['message'] = strtr($record['message'], $replacements); + + return $record; + } +} diff --git a/tests/Monolog/PsrLogCompatTest.php b/tests/Monolog/PsrLogCompatTest.php new file mode 100644 index 00000000..ab899449 --- /dev/null +++ b/tests/Monolog/PsrLogCompatTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +use Monolog\Handler\TestHandler; +use Monolog\Formatter\LineFormatter; +use Monolog\Processor\PsrLogMessageProcessor; +use Psr\Log\Test\LoggerInterfaceTest; + +class PsrLogCompatTest extends LoggerInterfaceTest +{ + private $handler; + + public function getLogger() + { + $logger = new Logger('foo'); + $logger->pushHandler($handler = new TestHandler); + $logger->pushProcessor(new PsrLogMessageProcessor); + $handler->setFormatter(new LineFormatter('%level_name% %message%')); + + $this->handler = $handler; + + return $logger; + } + + public function getLogs() + { + $convert = function ($record) { + $lower = function ($match) { + return strtolower($match[0]); + }; + + return preg_replace_callback('{^[A-Z]+}', $lower, $record['formatted']); + }; + + return array_map($convert, $this->handler->getRecords()); + } +}