Skip to content

Commit 4a10c2c

Browse files
committed
[FrameworkBundle] Add configuration for profiler log channels
1 parent 30e817a commit 4a10c2c

File tree

5 files changed

+188
-0
lines changed

5 files changed

+188
-0
lines changed

src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php

+27
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,27 @@
1616

1717
class DebugProcessor implements DebugLoggerInterface
1818
{
19+
private $channels = array();
20+
private $channelsExclusive = true;
1921
private $records = array();
2022
private $errorCount = 0;
2123

24+
/**
25+
* @param array $channels
26+
* @param bool $exclude
27+
*/
28+
public function setFilterChannels(array $channels, $exclude = true)
29+
{
30+
$this->channels = $channels;
31+
$this->channelsExclusive = (bool)$exclude;
32+
}
33+
2234
public function __invoke(array $record)
2335
{
36+
if ($this->isFiltered($record)) {
37+
return $record;
38+
}
39+
2440
$this->records[] = array(
2541
'timestamp' => $record['datetime']->getTimestamp(),
2642
'message' => $record['message'],
@@ -40,6 +56,17 @@ public function __invoke(array $record)
4056
return $record;
4157
}
4258

59+
private function isFiltered(array $record)
60+
{
61+
if ($this->channelsExclusive && !in_array($record['channel'], $this->channels)) {
62+
return false;
63+
} elseif (!$this->channelsExclusive && in_array($record['channel'], $this->channels)) {
64+
return false;
65+
}
66+
67+
return true;
68+
}
69+
4370
/**
4471
* {@inheritdoc}
4572
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Monolog\Tests\Processor;
13+
14+
use Monolog\Handler\TestHandler;
15+
use Monolog\Logger;
16+
use PHPUnit\Framework\TestCase;
17+
use Symfony\Bridge\Monolog\Processor\DebugProcessor;
18+
19+
class DebugProcessorTest extends TestCase
20+
{
21+
public function testNoChannelsAreFilteredByDefault()
22+
{
23+
$handler = new TestHandler();
24+
$processor = new DebugProcessor();
25+
26+
$aLogger = new Logger('a', array($handler), array($processor));
27+
$bLogger = new Logger('b', array($handler), array($processor));
28+
29+
$aLogger->info('test A');
30+
$bLogger->info('test B');
31+
32+
$logs = $processor->getLogs();
33+
$this->assertCount(2, $logs);
34+
35+
$this->assertEquals('a', $logs[0]['channel']);
36+
$this->assertEquals('test A', $logs[0]['message']);
37+
38+
$this->assertEquals('b', $logs[1]['channel']);
39+
$this->assertEquals('test B', $logs[1]['message']);
40+
}
41+
42+
public function testExcludedChannels()
43+
{
44+
$handler = new TestHandler();
45+
46+
$processor = new DebugProcessor();
47+
$processor->setFilterChannels(['a'], true);
48+
49+
$aLogger = new Logger('a', array($handler), array($processor));
50+
$bLogger = new Logger('b', array($handler), array($processor));
51+
52+
$aLogger->info('test A');
53+
$bLogger->info('test B');
54+
55+
$logs = $processor->getLogs();
56+
$this->assertCount(1, $logs);
57+
58+
$this->assertEquals('b', $logs[0]['channel']);
59+
$this->assertEquals('test B', $logs[0]['message']);
60+
}
61+
62+
public function testIncludedChannels()
63+
{
64+
$handler = new TestHandler();
65+
66+
$processor = new DebugProcessor();
67+
$processor->setFilterChannels(['a'], false);
68+
69+
$aLogger = new Logger('a', array($handler), array($processor));
70+
$bLogger = new Logger('b', array($handler), array($processor));
71+
72+
$aLogger->info('test A');
73+
$bLogger->info('test B');
74+
75+
$logs = $processor->getLogs();
76+
$this->assertCount(1, $logs);
77+
78+
$this->assertEquals('a', $logs[0]['channel']);
79+
$this->assertEquals('test A', $logs[0]['message']);
80+
}
81+
}

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CHANGELOG
1010
require symfony/stopwatch` in your `dev` environment.
1111
* Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`.
1212
* Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods.
13+
* Added a configuration to exclude logging channels from the profiler by setting `framework.profiler.log_channels`.
1314

1415
3.3.0
1516
-----

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

+59
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
1818
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
1919
use Symfony\Component\Config\Definition\ConfigurationInterface;
20+
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
2021
use Symfony\Component\Form\Form;
2122
use Symfony\Component\Serializer\Serializer;
2223
use Symfony\Component\Translation\Translator;
@@ -219,6 +220,64 @@ private function addProfilerSection(ArrayNodeDefinition $rootNode)
219220
->booleanNode('only_exceptions')->defaultFalse()->end()
220221
->booleanNode('only_master_requests')->defaultFalse()->end()
221222
->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end()
223+
->arrayNode('log_channels')
224+
->info('list of log channels to handle in profiler')
225+
->canBeUnset()
226+
->beforeNormalization()
227+
->ifString()
228+
->then(function ($v) { return array('channels' => array($v)); })
229+
->end()
230+
->beforeNormalization()
231+
->ifTrue(function ($v) { return is_array($v) && is_numeric(key($v)); })
232+
->then(function ($v) { return array('channels' => $v); })
233+
->end()
234+
->validate()
235+
->ifTrue(function ($v) { return empty($v); })
236+
->thenUnset()
237+
->end()
238+
->validate()
239+
->always(function ($v) {
240+
$isExclusive = null;
241+
if (isset($v['type'])) {
242+
$isExclusive = 'exclusive' === $v['type'];
243+
}
244+
245+
$channels = array();
246+
foreach ($v['channels'] as $channel) {
247+
if (0 === strpos($channel, '!')) {
248+
if (false === $isExclusive) {
249+
throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in profiler log_channels list.');
250+
}
251+
$channels[] = substr($channel, 1);
252+
$isExclusive = true;
253+
} else {
254+
if (true === $isExclusive) {
255+
throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in profiler log_channels list');
256+
}
257+
$channels[] = $channel;
258+
$isExclusive = false;
259+
}
260+
}
261+
262+
if (!count($channels)) {
263+
return null;
264+
}
265+
266+
return array('type' => $isExclusive ? 'exclusive' : 'inclusive', 'channels' => $channels);
267+
})
268+
->end()
269+
->children()
270+
->scalarNode('type')
271+
->validate()
272+
->ifNotInArray(array('inclusive', 'exclusive'))
273+
->thenInvalid('The type of log_channels has to be inclusive or exclusive')
274+
->end()
275+
->end()
276+
->arrayNode('channels')
277+
->prototype('scalar')->end()
278+
->end()
279+
->end()
280+
->end()
222281
->arrayNode('matcher')
223282
->canBeEnabled()
224283
->performNoDeepMerging()

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

+20
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ public function load(array $configs, ContainerBuilder $container)
231231
$this->registerCacheConfiguration($config['cache'], $container);
232232
$this->registerWorkflowConfiguration($config['workflows'], $container, $loader);
233233
$this->registerDebugConfiguration($config['php_errors'], $container, $loader);
234+
$this->registerDebugLoggerConfiguration($config['profiler'], $container);
234235

235236
if ($this->isConfigEnabled($container, $config['router'])) {
236237
$this->registerRouterConfiguration($config['router'], $container, $loader);
@@ -672,10 +673,29 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con
672673

673674
$definition->replaceArgument(4, $debug);
674675
$definition->replaceArgument(6, $debug);
676+
}
677+
678+
/**
679+
* Registers the debug log processor if debug is enabled
680+
*
681+
* @param array $config
682+
* @param ContainerBuilder $container
683+
*/
684+
private function registerDebugLoggerConfiguration(array $config, ContainerBuilder $container)
685+
{
686+
$debug = $container->getParameter('kernel.debug');
675687

676688
if ($debug && class_exists(DebugProcessor::class)) {
677689
$definition = new Definition(DebugProcessor::class);
678690
$definition->setPublic(false);
691+
692+
if (isset($config['log_channels'])) {
693+
$definition->addMethodCall('setChannels', [
694+
$config['log_channels']['channels'],
695+
$config['log_channels']['type'] === 'exclusive'
696+
]);
697+
}
698+
679699
$container->setDefinition('debug.log_processor', $definition);
680700
}
681701
}

0 commit comments

Comments
 (0)