Skip to content

Commit

Permalink
new EchoLogger, new min_level, ConsoleLogger deprecated
Browse files Browse the repository at this point in the history
  • Loading branch information
Christoph Singer committed Mar 7, 2018
1 parent 4af1608 commit 99857ca
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 34 deletions.
20 changes: 13 additions & 7 deletions README.md
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
74 changes: 74 additions & 0 deletions Wa72/SimpleLogger/AbstractSimpleLogger.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
namespace Wa72\SimpleLogger;


use Psr\Log\AbstractLogger;
use Psr\Log\LogLevel;

abstract class AbstractSimpleLogger extends AbstractLogger
{
protected $min_level = LogLevel::DEBUG;
protected $levels = [
LogLevel::DEBUG,
LogLevel::INFO,
LogLevel::NOTICE,
LogLevel::WARNING,
LogLevel::ERROR,
LogLevel::CRITICAL,
LogLevel::ALERT,
LogLevel::EMERGENCY
];

/**
* @param string $level
* @return boolean
*/
protected function min_level_reached($level)
{
return \array_search($level, $this->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";
}
}
23 changes: 21 additions & 2 deletions Wa72/SimpleLogger/ArrayLogger.php
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
<?php
namespace Wa72\SimpleLogger;
use Psr\Log\AbstractLogger;
use Psr\Log\LogLevel;

class ArrayLogger extends AbstractLogger
class ArrayLogger extends AbstractSimpleLogger
{
protected $memory = array();

public function __construct($min_level = LogLevel::DEBUG)
{
$this->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,
Expand Down Expand Up @@ -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']);
}
}
7 changes: 7 additions & 0 deletions Wa72/SimpleLogger/ConsoleLogger.php
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 26 additions & 0 deletions Wa72/SimpleLogger/EchoLogger.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
/**
* This is a logger implementing \Psr\Log\LoggerInterface (PSR-3) that just echos the log messages
*
*
* @author Christoph Singer
* @license MIT
*/
namespace Wa72\SimpleLogger;
use Psr\Log\LogLevel;

class EchoLogger extends AbstractSimpleLogger
{
public function __construct($min_level = LogLevel::DEBUG)
{
$this->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);
}
}
32 changes: 10 additions & 22 deletions Wa72/SimpleLogger/FileLogger.php
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
3 changes: 0 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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":"."
Expand Down

0 comments on commit 99857ca

Please sign in to comment.