diff --git a/README.md b/README.md old mode 100755 new mode 100644 index 1b4e1e4..eddf635 --- a/README.md +++ b/README.md @@ -9,23 +9,22 @@ like Monolog. If you just need to output a few log messages in a small PHP project but want to stick to the PSR-3 standard this package is for you. When your project grows you can simply replace it by a more advanced logging solution like Monolog. - Loggers ------- -- \Wa72\SimpleLogger\Filelogger: Log to a file +- \Wa72\SimpleLogger\EchoLogger: Just echo the log message + +- \Wa72\SimpleLogger\FileLogger: Log to a file - \Wa72\SimpleLogger\ArrayLogger: Keep log messages in an array for later use (e.g. display it to the user) -- \Wa72\SimpleLogger\ConsoleLogger: Log to the Symfony2 console +- \Wa72\SimpleLogger\ConsoleLogger: Log to the Symfony2 console => *DEPRECATED: use `Symfony\Component\Console\Logger\ConsoleLogger` instead* Installation ------------ -- using composer: add "wa72/simplelogger": "dev-master" to the "require" section of your composer.json - -- Without composer: just include the logger you need: FileLogger.php, ArrayLogger.php or ConsoleLogger.php. Make sure \Psr\Log\LoggerInterface is included as well. +- `composer require wa72/simplelogger` Usage @@ -36,8 +35,15 @@ $logger = new \Wa72\SimpleLogger\FileLogger('/path/to/logfile'); $logger->info('This is the first log message'); ``` +**NEW**: it's now possible to set a minimum log level in the constructor of FileLogger, EchoLogger and ArrayLogger: + +```php +$logger = new \Wa72\SimpleLogger\FileLogger('/path/to/logfile', \Psr\Log\LogLevel::ERROR); +$logger->info('This is the first log message'); // this message will be discarded +$logger->error('This is an error message'); // this message will be logged +``` -In one of my projects there was a "fetcher" class that fetched some information from a web service. It needed to log whether this fetch was successfull or not and how many data it fetched. It could be invoked either from the command line, by a background task, or by a user in the admin web page of the application. This was the use case for all 3 logger classes: +In one of my projects there was a "fetcher" class that fetched some information from a web service. It needed to log whether this fetch was successfull or not and how many data it fetched. It could be invoked either from the command line, by a background task, or by a user in the admin web page of the application. This was the use case for three logger classes: - the fetcher class itself just logs to any PSR-3 compliant logger diff --git a/Wa72/SimpleLogger/AbstractSimpleLogger.php b/Wa72/SimpleLogger/AbstractSimpleLogger.php new file mode 100644 index 0000000..94aa943 --- /dev/null +++ b/Wa72/SimpleLogger/AbstractSimpleLogger.php @@ -0,0 +1,74 @@ +levels) >= \array_search($this->min_level, $this->levels); + } + + /** + * Interpolates context values into the message placeholders. + * + * @author PHP Framework Interoperability Group + * + * @param string $message + * @param array $context + * @return string + */ + protected function interpolate($message, array $context) + { + if (false === strpos($message, '{')) { + return $message; + } + + $replacements = array(); + foreach ($context as $key => $val) { + if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { + $replacements["{{$key}}"] = $val; + } elseif ($val instanceof \DateTimeInterface) { + $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); + } elseif (\is_object($val)) { + $replacements["{{$key}}"] = '[object '.\get_class($val).']'; + } else { + $replacements["{{$key}}"] = '['.\gettype($val).']'; + } + } + + return strtr($message, $replacements); + } + + /** + * @param string $level + * @param string $message + * @param array $context + * @param string|null $timestamp A Timestamp string in format 'Y-m-d H:i:s', defaults to current time + * @return string + */ + protected function format($level, $message, $context, $timestamp = null) + { + if ($timestamp === null) $timestamp = date('Y-m-d H:i:s'); + return '[' . $timestamp . '] ' . strtoupper($level) . ': ' . $this->interpolate($message, $context) . "\n"; + } +} \ No newline at end of file diff --git a/Wa72/SimpleLogger/ArrayLogger.php b/Wa72/SimpleLogger/ArrayLogger.php old mode 100755 new mode 100644 index e07101d..d7dda9a --- a/Wa72/SimpleLogger/ArrayLogger.php +++ b/Wa72/SimpleLogger/ArrayLogger.php @@ -1,13 +1,21 @@ min_level = $min_level; + } + public function log($level, $message, array $context = array()) { + if (!$this->min_level_reached($level)) { + return; + } $this->memory[] = array( 'timestamp' => date('Y-m-d H:i:s'), 'level' => $level, @@ -65,4 +73,15 @@ public function clear() { $this->memory = array(); } + + /** + * Formatter function that can be used as parameter for the get() and getClear() methods + * + * @param array $a + * @return string + */ + public function formatter(array $a) + { + return $this->format($a['level'], $a['message'], $a['context'], $a['timestamp']); + } } diff --git a/Wa72/SimpleLogger/ConsoleLogger.php b/Wa72/SimpleLogger/ConsoleLogger.php old mode 100755 new mode 100644 index c3385c6..0f7a96f --- a/Wa72/SimpleLogger/ConsoleLogger.php +++ b/Wa72/SimpleLogger/ConsoleLogger.php @@ -3,6 +3,13 @@ use Psr\Log\AbstractLogger; use Symfony\Component\Console\Output\OutputInterface; +/** + * Class ConsoleLogger + * + * This class is deprecated because nowadays the Symfony Console component itself contains a ConsoleLogger + * + * @deprecated Use Symfony\Component\Console\Logger\ConsoleLogger instead + */ class ConsoleLogger extends AbstractLogger { /** * @var \Symfony\Component\Console\Output\OutputInterface diff --git a/Wa72/SimpleLogger/EchoLogger.php b/Wa72/SimpleLogger/EchoLogger.php new file mode 100644 index 0000000..c79bb8e --- /dev/null +++ b/Wa72/SimpleLogger/EchoLogger.php @@ -0,0 +1,26 @@ +min_level = $min_level; + } + + public function log($level, $message, array $context = array()) + { + if (!$this->min_level_reached($level)) { + return; + } + echo $this->format($level, $message, $context); + } +} diff --git a/Wa72/SimpleLogger/FileLogger.php b/Wa72/SimpleLogger/FileLogger.php old mode 100755 new mode 100644 index dad107c..aa9cbe9 --- a/Wa72/SimpleLogger/FileLogger.php +++ b/Wa72/SimpleLogger/FileLogger.php @@ -7,44 +7,32 @@ * @license MIT */ namespace Wa72\SimpleLogger; -class FileLogger extends \Psr\Log\AbstractLogger +use Psr\Log\LogLevel; + +class FileLogger extends AbstractSimpleLogger { protected $logfile; /** * @param string $logfile Filename to log messages to (complete path) - * @throws \InvalidArgumentException When logfile cannot be created or is not writeable + * @param string $min_level */ - public function __construct($logfile) + public function __construct($logfile, $min_level = LogLevel::DEBUG) { if (!file_exists($logfile)) { if (!touch($logfile)) throw new \InvalidArgumentException('Log file ' . $logfile . ' cannot be created'); } if (!is_writable($logfile)) throw new \InvalidArgumentException('Log file ' . $logfile . ' is not writeable'); $this->logfile = $logfile; + $this->min_level = $min_level; } public function log($level, $message, array $context = array()) { - $logline = '[' . date('Y-m-d H:i:s') . '] ' . strtoupper($level) . ': ' . $this->interpolate($message, $context) . "\n"; - file_put_contents($this->logfile, $logline, FILE_APPEND | LOCK_EX); - } - - /** - * Interpolates context values into the message placeholders. - * - * This function is just copied from the example in the PSR-3 spec - * - */ - protected function interpolate($message, array $context = array()) - { - // build a replacement array with braces around the context keys - $replace = array(); - foreach ($context as $key => $val) { - $replace['{' . $key . '}'] = $val; + if (!$this->min_level_reached($level)) { + return; } - - // interpolate replacement values into the message and return - return strtr($message, $replace); + $logline = $this->format($level, $message, $context); + file_put_contents($this->logfile, $logline, FILE_APPEND | LOCK_EX); } } diff --git a/composer.json b/composer.json index e55ec8e..94c3bcd 100644 --- a/composer.json +++ b/composer.json @@ -19,9 +19,6 @@ "provide": { "psr/log-implementation": "1.0.0" }, - "suggest": { - "symfony/console": "If you want to log to the Symfony console using Wa72ConsoleLogger" - }, "autoload":{ "psr-0":{ "Wa72\\SimpleLogger":"."