10000 Add options to monolog console handler and formatter by grongor · Pull Request #23929 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Add options to monolog console handler and formatter #23929

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

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

8000
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Symfony/Bridge/Monolog/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
CHANGELOG
=========

3.4.0
-----

* the `ConsoleHandler` class now accepts options for default formatter (`ConsoleFormatter`)
* added option `ignore_empty_context_and_extra` to `ConsoleFormatter`
* added option `remove_used_context_fields` to `ConsoleFormatter`

3.3.0
-----

Expand Down
33 changes: 24 additions & 9 deletions src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ public function __construct($options = array())
'date_format' => self::SIMPLE_DATE,
'colors' => true,
'multiline' => false,
'ignore_empty_context_and_extra' => false,
'remove_used_context_fields' => false,
), $options);

if (class_exists(VarCloner::class)) {
Expand Down Expand Up @@ -114,25 +116,28 @@ public function formatBatch(array $records)
*/
public function format(array $record)
{
$levelColor = self::$levelColorMap[$record['level']];

$record = $this->replacePlaceHolder($record);

$levelColor = self::$levelColorMap[$record['level']];
$context = $extra = '';
if (!empty($record['context']) || !$this->options['ignore_empty_context_and_extra']) {
Copy link
Member

Choose a reason for hiding this comment

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

we should not ignore an empty context if extras are not empty. Otherwise, you won't be able to know it is the extras (it will look like as if it is the context being dumped)

$context = $this->options['multiline'] ? "\n" : ' ';
$context .= $this->dumpData($record['context']);
}

if ($this->options['multiline']) {
$context = $extra = "\n";
} else {
$context = $extra = ' ';
if (!empty($record['extra']) || !$this->options['ignore_empty_context_and_extra']) {
$extra = $this->options['multiline'] ? "\n" : ' ';
$extra .= $this->dumpData($record['extra']);
}
$context .= $this->dumpData($record['context']);
$extra .= $this->dumpData($record['extra']);

$formatted = strtr($this->options['format'], array(
'%datetime%' => $record['datetime']->format($this->options['date_format']),
'%start_tag%' => sprintf('<%s>', $levelColor),
'%level_name%' => sprintf('%-9s', $record['level_name']),
'%end_tag%' => '</>',
'%channel%' => $record['channel'],
'%message%' => $this->replacePlaceHolder($record)['message'],
'%message%' => $record['message'],
'%context%' => $context,
'%extra%' => $extra,
));
Expand Down Expand Up @@ -179,13 +184,23 @@ private function replacePlaceHolder(array $record)

$replacements = array();
foreach ($context as $k => $v) {
$placeholder = '{'.$k.'}';
if (strpos($message, $placeholder) === false) {
continue;
}

// Remove quotes added by the dumper around string.
$v = trim($this->dumpData($v, false), '"');
$v = OutputFormatter::escape($v);
$replacements['{'.$k.'}'] = sprintf('<comment>%s</>', $v);
$replacements[$placeholder] = sprintf('<comment>%s</>', $v);

if ($this->options['remove_used_context_fields']) {
unset($context[$k]);
}
}

$record['message'] = strtr($message, $replacements);
$record['context'] = $context;

return $record;
}
Expand Down
20 changes: 15 additions & 5 deletions src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class ConsoleHandler extends AbstractProcessingHandler implements EventSubscribe
OutputInterface::VERBOSITY_DEBUG => Logger::DEBUG,
);
/** @var array */
private $formatterOptions;

/**
* Constructor.
*
Expand All @@ -64,15 +67,22 @@ class ConsoleHandler extends AbstractProcessingHandler implements EventSubscribe
* @param bool $bubble Whether the messages that are handled can bubble up the stack
* @param array $verbosityLevelMap Array that maps the OutputInterface verbosity to a minimum logging
* level (leave empty to use the default mapping)
* @param array $formatterOptions Array of options for default formatter (ConsoleFormatter)
*/
public function __construct(OutputInterface $output = null, $bubble = true, array $verbosityLevelMap = array())
{
public function __construct(
OutputInterface $output = null,
$bubble = true,
array $verbosityLevelMap = array(),
array $formatterOptions = array()
) {
parent::__construct(Logger::DEBUG, $bubble);
$this->output = $output;

if ($verbosityLevelMap) {
$this->verbosityLevelMap = $verbosityLevelMap;
}

$this->formatterOptions = $formatterOptions;
}

/**
Expand Down Expand Up @@ -165,13 +175,13 @@ protected function write(array $record)
protected function getDefaultFormatter()
{
if (!$this->output) {
return new ConsoleFormatter();
return new ConsoleFormatter($this->formatterOptions);
}

return new ConsoleFormatter(array(
return new ConsoleFormatter(array_replace(array(
'colors' => $this->output->isDecorated(),
'multiline' => OutputInterface::VERBOSITY_DEBUG <= $this->output->getVerbosity(),
));
), $this->formatterOptions));
}

/**
Expand Down
46 changes: 42 additions & 4 deletions src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,56 @@ public function testWritingAndFormatting()
->method('getVerbosity')
->will($this->returnValue(OutputInterface::VERBOSITY_DEBUG))
;
$message = <<<'EOL'
16:21:54 <fg=green>INFO </> <comment>[app]</> My info message <comment>bar</>
[
"foo" => "bar"
]
[]

EOL;
$output
->expects($this->once())
->method('write')
->with("16:21:54 <fg=green>INFO </> <comment>[app]</> My info message\n[]\n[]\n")
;
->with($message);

$handler = new ConsoleHandler(null, false);
$handler->setOutput($output);

$infoRecord = array(
'message' => 'My info message',
'context' => array(),
'message' => 'My info message {foo}',
'context' => array('foo' => 'bar'),
'level' => Logger::INFO,
'level_name' => Logger::getLevelName(Logger::INFO),
'channel' => 'app',
'datetime' => new \DateTime('2013-05-29 16:21:54'),
'extra' => array(),
);

$this->assertTrue($handler->handle($infoRecord), 'The handler finished handling the log as bubble is false.');
}

public function testWritingAndFormattingWithCustomFormattingOptions()
{
$output = $this->getMockBuilder('Symfony\Component\Console\Output\OutputInterface')->getMock();
$output
->expects($this->any())
->method('getVerbosity')
->will($this->returnValue(OutputInterface::VERBOSITY_DEBUG))
;
$output
->expects($this->once())
->method('write')
->with("16:21:54 <fg=green>INFO </> <comment>[app]</> My info message <comment>bar</>\n")
;

$formatterOptions = array('ignore_empty_context_and_extra' => true, 'remove_used_context_fields' => true);
$handler = new ConsoleHandler(null, false, array(), $formatterOptions);
$handler->setOutput($output);

$infoRecord = array(
'message' => 'My info message {foo}',
'context' => array('foo' => 'bar'),
'level' => Logger::INFO,
'level_name' => Logger::getLevelName(Logger::INFO),
'channel' => 'app',
Expand Down
0