Skip to content

Commit 81c547c

Browse files
committed
Add handler_default_channels configuration option
1 parent 0e136c5 commit 81c547c

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
@@ -383,6 +383,8 @@ public function getConfigTreeBuilder()
383383
$treeBuilder = new TreeBuilder('monolog');
384384
$rootNode = method_exists(TreeBuilder::class, 'getRootNode') ? $treeBuilder->getRootNode() : $treeBuilder->root('monolog');
385385

386+
$this->addChannelsSection($rootNode, 'handler_default_channels');
387+
386388
$handlers = $rootNode
387389
->fixXmlConfig('channel')
388390
->fixXmlConfig('handler')
@@ -621,6 +623,7 @@ public function getConfigTreeBuilder()
621623
->end()
622624
->scalarNode('formatter')->end()
623625
->booleanNode('nested')->defaultFalse()->end()
626+
->booleanNode('use_default_channels')->defaultTrue()->end()
624627
->end();
625628

626629
$this->addGelfSection($handlerNode);
@@ -793,9 +796,9 @@ public function getConfigTreeBuilder()
793796
return $treeBuilder;
794797
}
795798

796-
private function addGelfSection(ArrayNodeDefinition $handerNode)
799+
private function addGelfSection(ArrayNodeDefinition $handlerNode)
797800
{
798-
$handerNode
801+
$handlerNode
799802
->children()
800803
->arrayNode('publisher')
801804
->canBeUnset()
@@ -824,9 +827,9 @@ private function addGelfSection(ArrayNodeDefinition $handerNode)
824827
;
825828
}
826829

827-
private function addMongoSection(ArrayNodeDefinition $handerNode)
830+
private function addMongoSection(ArrayNodeDefinition $handlerNode)
828831
{
829-
$handerNode
832+
$handlerNode
830833
->children()
831834
->arrayNode('mongo')
832835
->canBeUnset()
@@ -864,9 +867,9 @@ private function addMongoSection(ArrayNodeDefinition $handerNode)
864867
;
865868
}
866869

867-
private function addElasticsearchSection(ArrayNodeDefinition $handerNode)
870+
private function addElasticsearchSection(ArrayNodeDefinition $handlerNode)
868871
{
869-
$handerNode
872+
$handlerNode
870873
->children()
871874
->arrayNode('elasticsearch')
872875
->canBeUnset()
@@ -896,9 +899,9 @@ private function addElasticsearchSection(ArrayNodeDefinition $handerNode)
896899
;
897900
}
898901

899-
private function addRedisSection(ArrayNodeDefinition $handerNode)
902+
private function addRedisSection(ArrayNodeDefinition $handlerNode)
900903
{
901-
$handerNode
904+
$handlerNode
902905
->children()
903906
->arrayNode('redis')
904907
->canBeUnset()
@@ -929,9 +932,9 @@ private function addRedisSection(ArrayNodeDefinition $handerNode)
929932
;
930933
}
931934

932-
private function addPredisSection(ArrayNodeDefinition $handerNode)
935+
private function addPredisSection(ArrayNodeDefinition $handlerNode)
933936
{
934-
$handerNode
937+
$handlerNode
935938
->children()
936939
->arrayNode('predis')
937940
->canBeUnset()
@@ -958,9 +961,9 @@ private function addPredisSection(ArrayNodeDefinition $handerNode)
958961
;
959962
}
960963

961-
private function addMailerSection(ArrayNodeDefinition $handerNode)
964+
private function addMailerSection(ArrayNodeDefinition $handlerNode)
962965
{
963-
$handerNode
966+
$handlerNode
964967
->children()
965968
->scalarNode('from_email')->end() // swift_mailer, native_mailer, symfony_mailer and flowdock
966969
->arrayNode('to_email') // swift_mailer, native_mailer and symfony_mailer
@@ -1005,9 +1008,9 @@ private function addMailerSection(ArrayNodeDefinition $handerNode)
10051008
;
10061009
}
10071010

1008-
private function addVerbosityLevelSection(ArrayNodeDefinition $handerNode)
1011+
private function addVerbosityLevelSection(ArrayNodeDefinition $handlerNode)
10091012
{
1010-
$handerNode
1013+
$handlerNode
10111014
->children()
10121015
->arrayNode('verbosity_levels') // console
10131016
->beforeNormalization()
@@ -1071,11 +1074,11 @@ private function addVerbosityLevelSection(ArrayNodeDefinition $handerNode)
10711074
;
10721075
}
10731076

1074-
private function addChannelsSection(ArrayNodeDefinition $handerNode)
1077+
private function addChannelsSection(ArrayNodeDefinition $handlerNode, string $nodeName = 'channels')
10751078
{
1076-
$handerNode
1079+
$handlerNode
10771080
->children()
1078-
->arrayNode('channels')
1081+
->arrayNode($nodeName)
10791082
->fixXmlConfig('channel', 'elements')
10801083
->canBeUnset()
10811084
->beforeNormalization()
@@ -1091,7 +1094,7 @@ private function addChannelsSection(ArrayNodeDefinition $handerNode)
10911094
->thenUnset()
10921095
->end()
10931096
->validate()
1094-
->always(function ($v) {
1097+
->always(function ($v) use ($nodeName) {
10951098
$isExclusive = null;
10961099
if (isset($v['type'])) {
10971100
$isExclusive = 'exclusive' === $v['type'];
@@ -1101,13 +1104,13 @@ private function addChannelsSection(ArrayNodeDefinition $handerNode)
11011104
foreach ($v['elements'] as $element) {
11021105
if (0 === strpos($element, '!')) {
11031106
if (false === $isExclusive) {
1104-
throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list.');
1107+
throw new InvalidConfigurationException(sprintf('Cannot combine exclusive/inclusive definitions in %s list.', $nodeName));
11051108
}
11061109
$elements[] = substr($element, 1);
11071110
$isExclusive = true;
11081111
} else {
11091112
if (true === $isExclusive) {
1110-
throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list');
1113+
throw new InvalidConfigurationException(sprintf('Cannot combine exclusive/inclusive definitions in %s list', $nodeName));
11111114
}
11121115
$elements[] = $element;
11131116
$isExclusive = false;
@@ -1126,7 +1129,7 @@ private function addChannelsSection(ArrayNodeDefinition $handerNode)
11261129
->scalarNode('type')
11271130
->validate()
11281131
->ifNotInArray(['inclusive', 'exclusive'])
1129-
->thenInvalid('The type of channels has to be inclusive or exclusive')
1132+
->thenInvalid(sprintf('The type of %s has to be inclusive or exclusive', $nodeName))
11301133
->end()
11311134
->end()
11321135
->arrayNode('elements')

DependencyInjection/MonologExtension.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ public function load(array $configs, ContainerBuilder $container)
7474
$handlers[$handler['priority']][] = [
7575
'id' => $this->buildHandler($container, $name, $handler),
7676
'channels' => empty($handler['channels']) ? null : $handler['channels'],
77+
'use_default_channels' => $handler['use_default_channels'],
7778
];
7879
}
7980

@@ -90,10 +91,19 @@ public function load(array $configs, ContainerBuilder $container)
9091
}
9192
}
9293

94+
$defaultChannels = $config['handler_default_channels'] ?? null;
9395
$handlersToChannels = [];
9496
foreach ($sortedHandlers as $handler) {
9597
if (!in_array($handler['id'], $this->nestedHandlers)) {
96-
$handlersToChannels[$handler['id']] = $handler['channels'];
98+
$channels = $handler['channels'];
99+
if (null !== $defaultChannels && $handler['use_default_channels']) {
100+
if (null === $channels) {
101+
$channels = $defaultChannels;
102+
} elseif ($channels['type'] === $defaultChannels['type']) {
103+
$channels['elements'] = array_unique(array_merge($channels['elements'], $defaultChannels['elements']));
104+
}
105+
}
106+
$handlersToChannels[$handler['id']] = $channels;
97107
}
98108
}
99109
$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 = [
@@ -549,6 +574,28 @@ public function processPsr3MessagesProvider(): iterable
549574
];
550575
}
551576

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

Tests/DependencyInjection/FixtureMonologExtensionTest.php

+55
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,61 @@ public function testHandlersWithChannels()
182182
);
183183
}
184184

185+
public function testHandlersWithDefaultChannels()
186+
{
187+
$container = $this->getContainer('handlers_with_default_channels');
188+
189+
$this->assertFalse($container->hasParameter('monolog.handler_default_channels'));
190+
191+
$this->assertEquals(
192+
[
193+
'monolog.handler.one' => ['type' => 'inclusive', 'elements' => ['foo']],
194+
'monolog.handler.two' => ['type' => 'exclusive', 'elements' => ['bar', 'baz']],
195+
'monolog.handler.three' => ['type' => 'exclusive', 'elements' => ['bar', 'baz', 'foo']],
196+
'monolog.handler.four' => ['type' => 'exclusive', 'elements' => ['foo', 'bar']],
197+
'monolog.handler.five' => null,
198+
'monolog.handler.six' => ['type' => 'exclusive', 'elements' => ['foo', 'bar']],
199+
],
200+
$container->getParameter('monolog.handlers_to_channels')
201+
);
202+
203+
$this->assertTrue($container->hasDefinition('monolog.logger'));
204+
$this->assertTrue($container->hasDefinition('monolog.logger.foo'));
205+
$this->assertTrue($container->hasDefinition('monolog.logger.bar'));
206+
$this->assertTrue($container->hasDefinition('monolog.logger.baz'));
207+
$this->assertTrue($container->hasDefinition('monolog.handler.one'));
208+
$this->assertTrue($container->hasDefinition('monolog.handler.two'));
209+
$this->assertTrue($container->hasDefinition('monolog.handler.three'));
210+
$this->assertTrue($container->hasDefinition('monolog.handler.four'));
211+
$this->assertTrue($container->hasDefinition('monolog.handler.five'));
212+
$this->assertTrue($container->hasDefinition('monolog.handler.six'));
213+
214+
$logger = $container->getDefinition('monolog.logger');
215+
$this->assertCount(6, $logger->getMethodCalls());
216+
$this->assertDICDefinitionMethodCallAt(5, $logger, 'pushHandler', [new Reference('monolog.handler.two')]);
217+
$this->assertDICDefinitionMethodCallAt(4, $logger, 'pushHandler', [new Reference('monolog.handler.three')]);
218+
$this->assertDICDefinitionMethodCallAt(3, $logger, 'pushHandler', [new Reference('monolog.handler.four')]);
219+
$this->assertDICDefinitionMethodCallAt(2, $logger, 'pushHandler', [new Reference('monolog.handler.five')]);
220+
$this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', [new Reference('monolog.handler.six')]);
221+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'useMicrosecondTimestamps', ['%monolog.use_microseconds%']);
222+
223+
$logger = $container->getDefinition('monolog.logger.foo');
224+
$this->assertCount(3, $logger->getMethodCalls());
225+
$this->assertDICDefinitionMethodCallAt(2, $logger, 'pushHandler', [new Reference('monolog.handler.one')]);
226+
$this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', [new Reference('monolog.handler.two')]);
227+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', [new Reference('monolog.handler.five')]);
228+
229+
$logger = $container->getDefinition('monolog.logger.bar');
230+
$this->assertCount(1, $logger->getMethodCalls());
231+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', [new Reference('monolog.handler.five')]);
232+
233+
$logger = $container->getDefinition('monolog.logger.baz');
234+
$this->assertCount(3, $logger->getMethodCalls());
235+
$this->assertDICDefinitionMethodCallAt(2, $logger, 'pushHandler', [new Reference('monolog.handler.four')]);
236+
$this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', [new Reference('monolog.handler.five')]);
237+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', [new Reference('monolog.handler.six')]);
238+
}
239+
185240
/** @group legacy */
186241
public function testSingleEmailRecipient()
187242
{
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)