Skip to content

Commit 402f0fc

Browse files
committed
Add handler_default_channels configuration option
1 parent ed0e4a2 commit 402f0fc

File tree

7 files changed

+203
-22
lines changed

7 files changed

+203
-22
lines changed

DependencyInjection/Configuration.php

+24-21
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,8 @@ public function getConfigTreeBuilder(): TreeBuilder
386386
$treeBuilder = new TreeBuilder('monolog');
387387
$rootNode = $treeBuilder->getRootNode();
388388

389+
$this->addChannelsSection($rootNode, 'handler_default_channels');
390+
389391
$handlers = $rootNode
390392
->fixXmlConfig('channel')
391393
->fixXmlConfig('handler')
@@ -625,6 +627,7 @@ public function getConfigTreeBuilder(): TreeBuilder
625627
->end()
626628
->scalarNode('formatter')->end()
627629
->booleanNode('nested')->defaultFalse()->end()
630+
->booleanNode('use_default_channels')->defaultTrue()->end()
628631
->end();
629632

630633
$this->addGelfSection($handlerNode);
@@ -801,9 +804,9 @@ public function getConfigTreeBuilder(): TreeBuilder
801804
return $treeBuilder;
802805
}
803806

804-
private function addGelfSection(ArrayNodeDefinition $handerNode)
807+
private function addGelfSection(ArrayNodeDefinition $handlerNode)
805808
{
806-
$handerNode
809+
$handlerNode
807810
->children()
808811
->arrayNode('publisher')
809812
->canBeUnset()
@@ -832,9 +835,9 @@ private function addGelfSection(ArrayNodeDefinition $handerNode)
832835
;
833836
}
834837

835-
private function addMongoSection(ArrayNodeDefinition $handerNode)
838+
private function addMongoSection(ArrayNodeDefinition $handlerNode)
836839
{
837-
$handerNode
840+
$handlerNode
838841
->children()
839842
->arrayNode('mongo')
840843
->canBeUnset()
@@ -872,9 +875,9 @@ private function addMongoSection(ArrayNodeDefinition $handerNode)
872875
;
873876
}
874877

875-
private function addElasticsearchSection(ArrayNodeDefinition $handerNode)
878+
private function addElasticsearchSection(ArrayNodeDefinition $handlerNode)
876879
{
877-
$handerNode
880+
$handlerNode
878881
->children()
879882
->arrayNode('elasticsearch')
880883
->canBeUnset()
@@ -904,9 +907,9 @@ private function addElasticsearchSection(ArrayNodeDefinition $handerNode)
904907
;
905908
}
906909

907-
private function addRedisSection(ArrayNodeDefinition $handerNode)
910+
private function addRedisSection(ArrayNodeDefinition $handlerNode)
908911
{
909-
$handerNode
912+
$handlerNode
910913
->children()
911914
->arrayNode('redis')
912915
->canBeUnset()
@@ -937,9 +940,9 @@ private function addRedisSection(ArrayNodeDefinition $handerNode)
937940
;
938941
}
939942

940-
private function addPredisSection(ArrayNodeDefinition $handerNode)
943+
private function addPredisSection(ArrayNodeDefinition $handlerNode)
941944
{
942-
$handerNode
945+
$handlerNode
943946
->children()
944947
->arrayNode('predis')
945948
->canBeUnset()
@@ -966,9 +969,9 @@ private function addPredisSection(ArrayNodeDefinition $handerNode)
966969
;
967970
}
968971

969-
private function addMailerSection(ArrayNodeDefinition $handerNode)
972+
private function addMailerSection(ArrayNodeDefinition $handlerNode)
970973
{
971-
$handerNode
974+
$handlerNode
972975
->children()
973976
->scalarNode('from_email')->end() // swift_mailer, native_mailer, symfony_mailer and flowdock
974977
->arrayNode('to_email') // swift_mailer, native_mailer and symfony_mailer
@@ -1013,9 +1016,9 @@ private function addMailerSection(ArrayNodeDefinition $handerNode)
10131016
;
10141017
}
10151018

1016-
private function addVerbosityLevelSection(ArrayNodeDefinition $handerNode)
1019+
private function addVerbosityLevelSection(ArrayNodeDefinition $handlerNode)
10171020
{
1018-
$handerNode
1021+
$handlerNode
10191022
->children()
10201023
->arrayNode('verbosity_levels') // console
10211024
->beforeNormalization()
@@ -1073,11 +1076,11 @@ private function addVerbosityLevelSection(ArrayNodeDefinition $handerNode)
10731076
;
10741077
}
10751078

1076-
private function addChannelsSection(ArrayNodeDefinition $handerNode)
1079+
private function addChannelsSection(ArrayNodeDefinition $handlerNode, string $nodeName = 'channels')
10771080
{
1078-
$handerNode
1081+
$handlerNode
10791082
->children()
1080-
->arrayNode('channels')
1083+
->arrayNode($nodeName)
10811084
->fixXmlConfig('channel', 'elements')
10821085
->canBeUnset()
10831086
->beforeNormalization()
@@ -1093,7 +1096,7 @@ private function addChannelsSection(ArrayNodeDefinition $handerNode)
10931096
->thenUnset()
10941097
->end()
10951098
->validate()
1096-
->always(function ($v) {
1099+
->always(function ($v) use ($nodeName) {
10971100
$isExclusive = null;
10981101
if (isset($v['type'])) {
10991102
$isExclusive = 'exclusive' === $v['type'];
@@ -1103,13 +1106,13 @@ private function addChannelsSection(ArrayNodeDefinition $handerNode)
11031106
foreach ($v['elements'] as $element) {
11041107
if (0 === strpos($element, '!')) {
11051108
if (false === $isExclusive) {
1106-
throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list.');
1109+
throw new InvalidConfigurationException(\sprintf('Cannot combine exclusive/inclusive definitions in %s list.', $nodeName));
11071110
}
11081111
$elements[] = substr($element, 1);
11091112
$isExclusive = true;
11101113
} else {
11111114
if (true === $isExclusive) {
1112-
throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list');
1115+
throw new InvalidConfigurationException(\sprintf('Cannot combine exclusive/inclusive definitions in %s list', $nodeName));
11131116
}
11141117
$elements[] = $element;
11151118
$isExclusive = false;
@@ -1128,7 +1131,7 @@ private function addChannelsSection(ArrayNodeDefinition $handerNode)
11281131
->scalarNode('type')
11291132
->validate()
11301133
->ifNotInArray(['inclusive', 'exclusive'])
1131-
->thenInvalid('The type of channels has to be inclusive or exclusive')
1134+
->thenInvalid(\sprintf('The type of %s has to be inclusive or exclusive', $nodeName))
11321135
->end()
11331136
->end()
11341137
->arrayNode('elements')

DependencyInjection/MonologExtension.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public function load(array $configs, ContainerBuilder $container)
7676
$handlers[$handler['priority']][] = [
7777
'id' => $this->buildHandler($container, $name, $handler),
7878
'channels' => empty($handler['channels']) ? null : $handler['channels'],
79+
'use_default_channels' => $handler['use_default_channels'],
7980
];
8081
}
8182

@@ -92,10 +93,19 @@ public function load(array $configs, ContainerBuilder $container)
9293
}
9394
}
9495

96+
$defaultChannels = $config['handler_default_channels'] ?? null;
9597
$handlersToChannels = [];
9698
foreach ($sortedHandlers as $handler) {
9799
if (!\in_array($handler['id'], $this->nestedHandlers)) {
98-
$handlersToChannels[$handler['id']] = $handler['channels'];
100+
$channels = $handler['channels'];
101+
if (null !== $defaultChannels && $handler['use_default_channels']) {
102+
if (null === $channels) {
103+
$channels = $defaultChannels;
104+
} elseif ($channels['type'] === $defaultChannels['type']) {
105+
$channels['elements'] = array_unique(array_merge($channels['elements'], $defaultChannels['elements']));
106+
}
107+
}
108+
$handlersToChannels[$handler['id']] = $channels;
99109
}
100110
}
101111
$container->setParameter('monolog.handlers_to_channels', $handlersToChannels);

Resources/config/schema/monolog-1.0.xsd

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<xsd:choice minOccurs="0" maxOccurs="unbounded">
1212
<xsd:element name="handler" type="handler" />
1313
<xsd:element name="channel" type="xsd:string" />
14+
<xsd:element name="handler-default-channels" type="channels" minOccurs="0" maxOccurs="1" />
1415
</xsd:choice>
1516
</xsd:complexType>
1617

@@ -92,6 +93,7 @@
9293
<xsd:attribute name="webhook-url" type="xsd:string" />
9394
<xsd:attribute name="slack-team" type="xsd:string" />
9495
<xsd:attribute name="region" type="xsd:string" />
96+
<xsd:attribute name="use-default-channels" type="xsd:boolean" />
9597
</xsd:complexType>
9698

9799
<xsd:simpleType name="level">

Tests/DependencyInjection/ConfigurationTest.php

+47
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,31 @@ public function testWithType()
323323
$this->assertEquals('B', $config['handlers']['foo']['channels']['elements'][1]);
324324
}
325325

326+
public function testWithUseDefaultChannels()
327+
{
328+
$configs = [
329+
[
330+
'handlers' => [
331+
'foo' => [
332+
'type' => 'stream',
333+
'path' => '/foo',
334+
'use_default_channels' => true,
335+
],
336+
'bar' => [
337+
'type' => 'stream',
338+
'path' => '/bar',
339+
'use_default_channels' => false,
340+
],
341+
],
342+
],
343+
];
344+
345+
$config = $this->process($configs);
346+
347+
$this->assertTrue($config['handlers']['foo']['use_default_channels']);
348+
$this->assertFalse($config['handlers']['bar']['use_default_channels']);
349+
}
350+
326351
public function testWithFilePermission()
327352
{
328353
$configs = [
@@ -548,6 +573,28 @@ public function processPsr3MessagesProvider(): iterable
548573
];
549574
}
550575

576+
/**
577+
* @dataProvider provideHandlerDefaultChannels
578+
*/
579+
public function testHandlerDefaultChannels($configuration, ?array $processedConfiguration)
580+
{
581+
$config = $this->process([['handler_default_channels' => $configuration]]);
582+
583+
$this->assertEquals($processedConfiguration, $config['handler_default_channels']);
584+
}
585+
586+
public static function provideHandlerDefaultChannels(): iterable
587+
{
588+
yield 'None' => [null, null];
589+
yield 'Empty array' => [[], null];
590+
yield 'As string' => ['!foo', ['type' => 'exclusive', 'elements' => ['foo']]];
591+
yield 'As array' => [['foo', 'bar'], ['type' => 'inclusive', 'elements' => ['foo', 'bar']]];
592+
yield 'With elements key' => [['elements' => ['!foo', '!bar']], ['type' => 'exclusive', 'elements' => ['foo', 'bar']]];
593+
yield 'With type key' => [['type' => 'exclusive', 'elements' => ['!foo']], ['type' => 'exclusive', 'elements' => ['foo']]];
594+
yield 'XML' => [['channel' => ['foo', 'bar']], ['type' => 'inclusive', 'elements' => ['foo', 'bar']]];
595+
yield 'XML with type' => [['type' => 'exclusive', 'channel' => ['!foo']], ['type' => 'exclusive', 'elements' => ['foo']]];
596+
}
597+
551598
/**
552599
* Processes an array of configurations and returns a compiled version.
553600
*

Tests/DependencyInjection/FixtureMonologExtensionTest.php

+55
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,61 @@ public function testHandlersWithChannels()
145145
);
146146
}
147147

148+
public function testHandlersWithDefaultChannels()
149+
{
150+
$container = $this->getContainer('handlers_with_default_channels');
151+
152+
$this->assertFalse($container->hasParameter('monolog.handler_default_channels'));
153+
154+
$this->assertEquals(
155+
[
156+
'monolog.handler.one' => ['type' => 'inclusive', 'elements' => ['foo']],
157+
'monolog.handler.two' => ['type' => 'exclusive', 'elements' => ['bar', 'baz']],
158+
'monolog.handler.three' => ['type' => 'exclusive', 'elements' => ['bar', 'baz', 'foo']],
159+
'monolog.handler.four' => ['type' => 'exclusive', 'elements' => ['foo', 'bar']],
160+
'monolog.handler.five' => null,
161+
'monolog.handler.six' => ['type' => 'exclusive', 'elements' => ['foo', 'bar']],
162+
],
163+
$container->getParameter('monolog.handlers_to_channels')
164+
);
165+
166+
$this->assertTrue($container->hasDefinition('monolog.logger'));
167+
$this->assertTrue($container->hasDefinition('monolog.logger.foo'));
168+
$this->assertTrue($container->hasDefinition('monolog.logger.bar'));
169+
$this->assertTrue($container->hasDefinition('monolog.logger.baz'));
170+
$this->assertTrue($container->hasDefinition('monolog.handler.one'));
171+
$this->assertTrue($container->hasDefinition('monolog.handler.two'));
172+
$this->assertTrue($container->hasDefinition('monolog.handler.three'));
173+
$this->assertTrue($container->hasDefinition('monolog.handler.four'));
174+
$this->assertTrue($container->hasDefinition('monolog.handler.five'));
175+
$this->assertTrue($container->hasDefinition('monolog.handler.six'));
176+
177+
$logger = $container->getDefinition('monolog.logger');
178+
$this->assertCount(6, $logger->getMethodCalls());
179+
$this->assertDICDefinitionMethodCallAt(5, $logger, 'pushHandler', [new Reference('monolog.handler.two')]);
180+
$this->assertDICDefinitionMethodCallAt(4, $logger, 'pushHandler', [new Reference('monolog.handler.three')]);
181+
$this->assertDICDefinitionMethodCallAt(3, $logger, 'pushHandler', [new Reference('monolog.handler.four')]);
182+
$this->assertDICDefinitionMethodCallAt(2, $logger, 'pushHandler', [new Reference('monolog.handler.five')]);
183+
$this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', [new Reference('monolog.handler.six')]);
184+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'useMicrosecondTimestamps', ['%monolog.use_microseconds%']);
185+
186+
$logger = $container->getDefinition('monolog.logger.foo');
187+
$this->assertCount(3, $logger->getMethodCalls());
188+
$this->assertDICDefinitionMethodCallAt(2, $logger, 'pushHandler', [new Reference('monolog.handler.one')]);
189+
$this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', [new Reference('monolog.handler.two')]);
190+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', [new Reference('monolog.handler.five')]);
191+
192+
$logger = $container->getDefinition('monolog.logger.bar');
193+
$this->assertCount(1, $logger->getMethodCalls());
194+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', [new Reference('monolog.handler.five')]);
195+
196+
$logger = $container->getDefinition('monolog.logger.baz');
197+
$this->assertCount(3, $logger->getMethodCalls());
198+
$this->assertDICDefinitionMethodCallAt(2, $logger, 'pushHandler', [new Reference('monolog.handler.four')]);
199+
$this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', [new Reference('monolog.handler.five')]);
200+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', [new Reference('monolog.handler.six')]);
201+
}
202+
148203
/** @group legacy */
149204
public function testSingleEmailRecipient()
150205
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xmlns:monolog="http://symfony.com/schema/dic/monolog"
6+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
7+
http://symfony.com/schema/dic/monolog http://symfony.com/schema/dic/monolog/monolog-1.0.xsd">
8+
9+
<monolog:config>
10+
<monolog:channel>foo</monolog:channel>
11+
<monolog:channel>bar</monolog:channel>
12+
<monolog:channel>baz</monolog:channel>
13+
14+
<monolog:handler-default-channels>
15+
<monolog:channel>!foo</monolog:channel>
16+
<monolog:channel>!bar</monolog:channel>
17+
</monolog:handler-default-channels>
18+
19+
<monolog:handler name="one" type="stream" use-default-channels="true">
20+
<monolog:channels>
21+
<monolog:channel>foo</monolog:channel>
22+
</monolog:channels>
23+
</monolog:handler>
24+
<monolog:handler name="two" type="stream" use-default-channels="false">
25+
<monolog:channels>
26+
<monolog:channel>!bar</monolog:channel>
27+
<monolog:channel>!baz</monolog:channel>
28+
</monolog:channels>
29+
</monolog:handler>
30+
<monolog:handler name="three" type="stream" use-default-channels="true">
31+
<monolog:channels>
32+
<monolog:channel>!bar</monolog:channel>
33+
<monolog:channel>!baz</monolog:channel>
34+
</monolog:channels>
35+
</monolog:handler>
36+
<monolog:handler name="four" type="stream" use-default-channels="true" />
37+
<monolog:handler name="five" type="stream" use-default-channels="false" />
38+
<monolog:handler name="six" type="stream" />
39+
</monolog:config>
40+
</container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
monolog:
2+
channels: [ 'foo', 'bar', 'baz' ]
3+
handler_default_channels: [ '!foo', '!bar' ]
4+
handlers:
5+
one:
6+
type: stream
7+
use_default_channels: true
8+
channels: foo
9+
two:
10+
type: stream
11+
use_default_channels: false
12+
channels: [ '!bar', '!baz' ]
13+
three:
14+
type: stream
15+
use_default_channels: true
16+
channels: [ '!bar', '!baz' ]
17+
four:
18+
type: stream
19+
use_default_channels: true
20+
five:
21+
type: stream
22+
use_default_channels: false
23+
six:
24+
type: stream

0 commit comments

Comments
 (0)