Skip to content

[Console] Added standalone PSR-3 compliant logger #10194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 19, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions src/Symfony/Component/Console/Logger/ConsoleLogger.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Console\Logger;

use Psr\Log\AbstractLogger;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;

/**
* PSR-3 compliant console logger
*
* @author Kévin Dunglas <dunglas@gmail.com>
* @link http://www.php-fig.org/psr/psr-3/
*/
class ConsoleLogger extends AbstractLogger
{
const INFO = 'info';
const ERROR = 'error';

/**
* @var OutputInterface
*/
private $output;
/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better leave line breaks here?

* @var array
*/
private $verbosityLevelMap = array(
LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG
);
/**
* @var array
*/
private $formatLevelMap = array(
LogLevel::EMERGENCY => self::ERROR,
LogLevel::ALERT => self::ERROR,
LogLevel::CRITICAL => self::ERROR,
LogLevel::ERROR => self::ERROR,
LogLevel::WARNING => self::INFO,
LogLevel::NOTICE => self::INFO,
LogLevel::INFO => self::INFO,
LogLevel::DEBUG => self::INFO
);

/**
* @param OutputInterface $output
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In-correct/complete docblock.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sstok What's the problem with this annotation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The phpdoc is incomplete, there is only the type but not the actual param name

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks I got it.

* @param array $verbosityLevelMap
* @param array $formatLevelMap
*/
public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
{
$this->output = $output;
$this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
$this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
}

/**
* {@inheritdoc}
*/
public function log($level, $message, array $context = array())
{
if (!isset($this->verbosityLevelMap[$level])) {
throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be an OutOfBoundsException ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The InvalidArgumentException in defined in PSR-3

}

// Write to the error output if necessary and available
if ($this->formatLevelMap[$level] === self::ERROR && $this->output instanceof ConsoleOutputInterface) {
$output = $this->output->getErrorOutput();
} else {
$output = $this->output;
}

if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
$output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
}
}

/**
* Interpolates context values into the message placeholders
*
* @author PHP Framework Interoperability Group
* @param string $message
* @param array $context
* @return string
*/
private function interpolate($message, array $context)
{
// build a replacement array with braces around the context keys
$replace = array();
foreach ($context as $key => $val) {
if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
$replace[sprintf('{%s}', $key)] = $val;
}
}

// interpolate replacement values into the message and return
return strtr($message, $replace);
}
}
36 changes: 36 additions & 0 deletions src/Symfony/Component/Console/Tests/Fixtures/DummyOutput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Console\Tests\Fixtures;

use Symfony\Component\Console\Output\BufferedOutput;

/**
* Dummy output
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class DummyOutput extends BufferedOutput
{
/**
* @return array
*/
public function getLogs()
{
$logs = array();
foreach (explode("\n", trim($this->fetch())) as $message) {
preg_match('/^\[(.*)\] (.*)/', $message, $matches);
$logs[] = sprintf('%s %s', $matches[1], $matches[2]);
}

return $logs;
}
}
58 changes: 58 additions & 0 deletions src/Symfony/Component/Console/Tests/Logger/ConsoleLoggerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Console\Tests\Logger;

use Psr\Log\Test\LoggerInterfaceTest;
use Psr\Log\LogLevel;
use Symfony\Component\Console\Logger\ConsoleLogger;
use Symfony\Component\Console\Tests\Fixtures\DummyOutput;
use Symfony\Component\Console\Output\OutputInterface;

/**
* Console logger test
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class ConsoleLoggerTest extends LoggerInterfaceTest
{
/**
* @var DummyOutput
*/
protected $output;

/**
* {@inheritdoc}
*/
public function getLogger()
{
$this->output = new DummyOutput(OutputInterface::VERBOSITY_VERBOSE);

return new ConsoleLogger($this->output, array(
LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
LogLevel::NOTICE => OutputInterface::VERBOSITY_NORMAL,
LogLevel::INFO => OutputInterface::VERBOSITY_NORMAL,
LogLevel::DEBUG => OutputInterface::VERBOSITY_NORMAL
));
}

/**
* {@inheritdoc}
*/
public function getLogs()
{
return $this->output->getLogs();
}
}
6 changes: 4 additions & 2 deletions src/Symfony/Component/Console/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
"php": ">=5.3.3"
},
"require-dev": {
"symfony/event-dispatcher": "~2.1"
"symfony/event-dispatcher": "~2.1",
"psr/log": "~1.0"
},
"suggest": {
"symfony/event-dispatcher": ""
"symfony/event-dispatcher": "",
"psr/log": "For using the console logger"
},
"autoload": {
"psr-0": { "Symfony\\Component\\Console\\": "" }
Expand Down