Skip to content

Commit 7018335

Browse files
committed
Merge remote branch 'stof/monolog'
* stof/monolog: [MonologBundle][BC break] Renamed the type to fingers_crossed and rotating_file [MonologBundle] Refactored the configuration to allow adding handlers
2 parents ceb2c97 + 723f7d4 commit 7018335

File tree

5 files changed

+193
-18
lines changed

5 files changed

+193
-18
lines changed

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ public function getConfigTreeBuilder()
4141
->children()
4242
->arrayNode('handlers')
4343
->canBeUnset()
44-
->performNoDeepMerging()
4544
->useAttributeAsKey('name')
4645
->prototype('array')
46+
->canBeUnset()
4747
->children()
4848
->scalarNode('type')
4949
->isRequired()
@@ -54,19 +54,21 @@ public function getConfigTreeBuilder()
5454
->end()
5555
->end()
5656
->scalarNode('id')->end()
57+
->scalarNode('priority')->defaultValue(0)->end()
5758
->scalarNode('level')->defaultValue('DEBUG')->end()
5859
->booleanNode('bubble')->defaultFalse()->end()
59-
->scalarNode('path')->end() // stream specific
60-
->scalarNode('ident')->end() // syslog specific
61-
->scalarNode('facility')->end() // syslog specific
62-
->scalarNode('action_level')->end() // fingerscrossed specific
63-
->scalarNode('buffer_size')->end() // fingerscrossed specific
64-
->scalarNode('handler')->end() // fingerscrossed specific
60+
->scalarNode('path')->end() // stream and rotating
61+
->scalarNode('ident')->end() // syslog
62+
->scalarNode('facility')->end() // syslog
63+
->scalarNode('max_files')->end() // rotating
64+
->scalarNode('action_level')->end() // fingers_crossed
65+
->scalarNode('buffer_size')->end() // fingers_crossed and buffer
66+
->scalarNode('handler')->end() // fingers_crossed and buffer
6567
->scalarNode('formatter')->end()
6668
->end()
6769
->append($this->getProcessorsNode())
6870
->validate()
69-
->ifTrue(function($v) { return 'fingerscrossed' === $v['type'] && !isset($v['handler']); })
71+
->ifTrue(function($v) { return ('fingers_crossed' === $v['type'] || 'buffer' === $v['type']) && 1 !== count($v['handler']); })
7072
->thenInvalid('The handler has to be specified to use a FingersCrossedHandler')
7173
->end()
7274
->validate()

src/Symfony/Bundle/MonologBundle/DependencyInjection/MonologExtension.php

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,19 @@ public function load(array $configs, ContainerBuilder $container)
5555

5656
$handlers = array();
5757
foreach ($config['handlers'] as $name => $handler) {
58-
$handlers[] = $this->buildHandler($container, $name, $handler);
58+
$handlers[] = array('id' => $this->buildHandler($container, $name, $handler), 'priority' => $handler['priority'] );
5959
}
6060

6161
$handlers = array_reverse($handlers);
62+
uasort($handlers, function($a, $b) {
63+
if ($a['priority'] == $b['priority']) {
64+
return 0;
65+
}
66+
return $a['priority'] < $b['priority'] ? -1 : 1;
67+
});
6268
foreach ($handlers as $handler) {
63-
if (!in_array($handler, $this->nestedHandlers)) {
64-
$logger->addMethodCall('pushHandler', array(new Reference($handler)));
69+
if (!in_array($handler['id'], $this->nestedHandlers)) {
70+
$logger->addMethodCall('pushHandler', array(new Reference($handler['id'])));
6571
}
6672
}
6773
}
@@ -118,7 +124,20 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
118124
));
119125
break;
120126

121-
case 'fingerscrossed':
127+
case 'rotating_file':
128+
if (!isset($handler['path'])) {
129+
$handler['path'] = '%kernel.logs_dir%/%kernel.environment%.log';
130+
}
131+
132+
$definition->setArguments(array(
133+
$handler['path'],
134+
isset($handler['max_files']) ? $handler['max_files'] : 0,
135+
$handler['level'],
136+
$handler['bubble'],
137+
));
138+
break;
139+
140+
case 'fingers_crossed':
122141
if (!isset($handler['action_level'])) {
123142
$handler['action_level'] = 'WARNING';
124143
}
@@ -134,6 +153,18 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
134153
));
135154
break;
136155

156+
case 'buffer':
157+
$nestedHandlerId = $this->getHandlerId($handler['handler']);
158+
array_push($this->nestedHandlers, $nestedHandlerId);
159+
160+
$definition->setArguments(array(
161+
new Reference($nestedHandlerId),
162+
isset($handler['buffer_size']) ? $handler['buffer_size'] : 0,
163+
$handler['level'],
164+
$handler['bubble'],
165+
));
166+
break;
167+
137168
case 'syslog':
138169
if (!isset($handler['ident'])) {
139170
$handler['ident'] = false;

src/Symfony/Bundle/MonologBundle/Resources/config/monolog.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
<parameters>
88
<parameter key="monolog.logger.class">Symfony\Bundle\MonologBundle\Logger\Logger</parameter>
99
<parameter key="monolog.handler.stream.class">Monolog\Handler\StreamHandler</parameter>
10-
<parameter key="monolog.handler.fingerscrossed.class">Monolog\Handler\FingersCrossedHandler</parameter>
10+
<parameter key="monolog.handler.fingers_crossed.class">Monolog\Handler\FingersCrossedHandler</parameter>
11+
<parameter key="monolog.handler.buffer.class">Monolog\Handler\BufferHandler</parameter>
12+
<parameter key="monolog.handler.rotating_file.class">Monolog\Handler\RotatingFileHandler</parameter>
1113
<parameter key="monolog.handler.syslog.class">Monolog\Handler\SyslogHandler</parameter>
1214
<parameter key="monolog.handler.null.class">Monolog\Handler\NullHandler</parameter>
1315
<parameter key="monolog.handler.test.class">Monolog\Handler\TestHandler</parameter>

src/Symfony/Bundle/MonologBundle/Resources/config/schema/monolog-1.0.xsd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<xsd:element name="processor" type="processor" />
2020
</xsd:choice>
2121
<xsd:attribute name="type" type="xsd:string" use="required" />
22+
<xsd:attribute name="priority" type="xsd:integer" />
2223
<xsd:attribute name="level" type="level" />
2324
<xsd:attribute name="bubble" type="xsd:boolean" />
2425
<xsd:attribute name="path" type="xsd:string" />
@@ -28,6 +29,7 @@
2829
<xsd:attribute name="facility" type="xsd:string" />
2930
<xsd:attribute name="action-level" type="level" />
3031
<xsd:attribute name="buffer-size" type="xsd:integer" />
32+
<xsd:attribute name="max-files" type="xsd:integer" />
3133
<xsd:attribute name="handler" type="xsd:string" />
3234
<xsd:attribute name="formatter" type="xsd:string" />
3335
</xsd:complexType>

src/Symfony/Bundle/MonologBundle/Tests/DependencyInjection/MonologExtensionTest.php

Lines changed: 143 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ class MonologExtensionTest extends TestCase
2020
{
2121
public function testLoadWithDefault()
2222
{
23-
// logger
2423
$container = new ContainerBuilder();
2524
$loader = new MonologExtension();
2625

@@ -38,7 +37,6 @@ public function testLoadWithDefault()
3837

3938
public function testLoadWithCustomValues()
4039
{
41-
// logger
4240
$container = new ContainerBuilder();
4341
$loader = new MonologExtension();
4442

@@ -56,13 +54,12 @@ public function testLoadWithCustomValues()
5654

5755
public function testLoadWithSeveralHandlers()
5856
{
59-
// logger
6057
$container = new ContainerBuilder();
6158
$loader = new MonologExtension();
6259

6360
$loader->load(array(array('handlers' => array(
6461
'custom' => array('type' => 'stream', 'path' => '/tmp/symfony.log', 'bubble' => true, 'level' => 'ERROR'),
65-
'main' => array('type' => 'fingerscrossed', 'action_level' => 'ERROR', 'handler' => 'nested'),
62+
'main' => array('type' => 'fingers_crossed', 'action_level' => 'ERROR', 'handler' => 'nested'),
6663
'nested' => array('type' => 'stream')
6764
))), $container);
6865
$this->assertTrue($container->hasDefinition('monolog.logger'));
@@ -79,10 +76,151 @@ public function testLoadWithSeveralHandlers()
7976
$this->assertDICConstructorArguments($handler, array('/tmp/symfony.log', \Monolog\Logger::ERROR, true));
8077

8178
$handler = $container->getDefinition('monolog.handler.main');
82-
$this->assertDICDefinitionClass($handler, '%monolog.handler.fingerscrossed.class%');
79+
$this->assertDICDefinitionClass($handler, '%monolog.handler.fingers_crossed.class%');
8380
$this->assertDICConstructorArguments($handler, array(new Reference('monolog.handler.nested'), \Monolog\Logger::ERROR, 0, false));
8481
}
8582

83+
public function testLoadWithOverwriting()
84+
{
85+
$container = new ContainerBuilder();
86+
$loader = new MonologExtension();
87+
88+
$loader->load(array(
89+
array('handlers' => array(
90+
'custom' => array('type' => 'stream', 'path' => '/tmp/symfony.log', 'bubble' => true, 'level' => 'ERROR'),
91+
'main' => array('type' => 'fingers_crossed', 'action_level' => 'ERROR', 'handler' => 'nested'),
92+
'nested' => array('type' => 'stream')
93+
)),
94+
array('handlers' => array(
95+
'custom' => array('type' => 'stream', 'path' => '/tmp/symfony.log', 'bubble' => true, 'level' => 'WARNING'),
96+
))
97+
), $container);
98+
$this->assertTrue($container->hasDefinition('monolog.logger'));
99+
$this->assertTrue($container->hasDefinition('monolog.handler.custom'));
100+
$this->assertTrue($container->hasDefinition('monolog.handler.main'));
101+
$this->assertTrue($container->hasDefinition('monolog.handler.nested'));
102+
103+
$logger = $container->getDefinition('monolog.logger');
104+
$this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', array(new Reference('monolog.handler.custom')));
105+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', array(new Reference('monolog.handler.main')));
106+
107+
$handler = $container->getDefinition('monolog.handler.custom');
108+
$this->assertDICDefinitionClass($handler, '%monolog.handler.stream.class%');
109+
$this->assertDICConstructorArguments($handler, array('/tmp/symfony.log', \Monolog\Logger::WARNING, true));
110+
111+
$handler = $container->getDefinition('monolog.handler.main');
112+
$this->assertDICDefinitionClass($handler, '%monolog.handler.fingers_crossed.class%');
113+
$this->assertDICConstructorArguments($handler, array(new Reference('monolog.handler.nested'), \Monolog\Logger::ERROR, 0, false));
114+
}
115+
116+
public function testLoadWithNewAtEnd()
117+
{
118+
$container = new ContainerBuilder();
119+
$loader = new MonologExtension();
120+
121+
$loader->load(array(
122+
array('handlers' => array(
123+
'custom' => array('type' => 'stream', 'path' => '/tmp/symfony.log', 'bubble' => true, 'level' => 'ERROR'),
124+
'main' => array('type' => 'fingers_crossed', 'action_level' => 'ERROR', 'handler' => 'nested'),
125+
'nested' => array('type' => 'stream')
126+
)),
127+
array('handlers' => array(
128+
'custom' => array('type' => 'stream', 'path' => '/tmp/symfony.log', 'bubble' => true, 'level' => 'WARNING'),
129+
'new' => array('type' => 'stream', 'path' => '/tmp/monolog.log', 'bubble' => true, 'level' => 'ERROR'),
130+
))
131+
), $container);
132+
$this->assertTrue($container->hasDefinition('monolog.logger'));
133+
$this->assertTrue($container->hasDefinition('monolog.handler.custom'));
134+
$this->assertTrue($container->hasDefinition('monolog.handler.main'));
135+
$this->assertTrue($container->hasDefinition('monolog.handler.nested'));
136+
$this->assertTrue($container->hasDefinition('monolog.handler.new'));
137+
138+
$logger = $container->getDefinition('monolog.logger');
139+
$this->assertDICDefinitionMethodCallAt(2, $logger, 'pushHandler', array(new Reference('monolog.handler.new')));
140+
$this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', array(new Reference('monolog.handler.custom')));
141+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', array(new Reference('monolog.handler.main')));
142+
143+
$handler = $container->getDefinition('monolog.handler.new');
144+
$this->assertDICDefinitionClass($handler, '%monolog.handler.stream.class%');
145+
$this->assertDICConstructorArguments($handler, array('/tmp/monolog.log', \Monolog\Logger::ERROR, true));
146+
}
147+
148+
public function testLoadWithNewAndPriority()
149+
{
150+
$container = new ContainerBuilder();
151+
$loader = new MonologExtension();
152+
153+
$loader->load(array(
154+
array('handlers' => array(
155+
'custom' => array('type' => 'stream', 'path' => '/tmp/symfony.log', 'bubble' => true, 'level' => 'ERROR'),
156+
'main' => array('type' => 'buffer', 'level' => 'INFO', 'handler' => 'nested'),
157+
'nested' => array('type' => 'stream')
158+
)),
159+
array('handlers' => array(
160+
'custom' => array('type' => 'stream', 'path' => '/tmp/symfony.log', 'bubble' => true, 'level' => 'WARNING'),
161+
'first' => array('type' => 'rotating_file', 'path' => '/tmp/monolog.log', 'bubble' => true, 'level' => 'ERROR', 'priority' => 3),
162+
'last' => array('type' => 'stream', 'path' => '/tmp/last.log', 'bubble' => true, 'level' => 'ERROR', 'priority' => -3),
163+
))
164+
), $container);
165+
$this->assertTrue($container->hasDefinition('monolog.logger'));
166+
$this->assertTrue($container->hasDefinition('monolog.handler.custom'));
167+
$this->assertTrue($container->hasDefinition('monolog.handler.main'));
168+
$this->assertTrue($container->hasDefinition('monolog.handler.nested'));
169+
$this->assertTrue($container->hasDefinition('monolog.handler.first'));
170+
$this->assertTrue($container->hasDefinition('monolog.handler.last'));
171+
172+
$logger = $container->getDefinition('monolog.logger');
173+
$this->assertDICDefinitionMethodCallAt(2, $logger, 'pushHandler', array(new Reference('monolog.handler.last')));
174+
$this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', array(new Reference('monolog.handler.custom')));
175+
$this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', array(new Reference('monolog.handler.main')));
176+
$this->assertDICDefinitionMethodCallAt(2, $logger, 'pushHandler', array(new Reference('monolog.handler.first')));
177+
178+
$handler = $container->getDefinition('monolog.handler.main');
179+
$this->assertDICDefinitionClass($handler, '%monolog.handler.buffer.class%');
180+
$this->assertDICConstructorArguments($handler, array(new Reference('monolog.handler.nested'), 0, \Monolog\Logger::INFO, false));
181+
182+
$handler = $container->getDefinition('monolog.handler.first');
183+
$this->assertDICDefinitionClass($handler, '%monolog.handler.rotating_file.class%');
184+
$this->assertDICConstructorArguments($handler, array('/tmp/monolog.log', 0, \Monolog\Logger::ERROR, true));
185+
186+
$handler = $container->getDefinition('monolog.handler.last');
187+
$this->assertDICDefinitionClass($handler, '%monolog.handler.stream.class%');
188+
$this->assertDICConstructorArguments($handler, array('/tmp/last.log', \Monolog\Logger::ERROR, true));
189+
}
190+
191+
/**
192+
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
193+
*/
194+
public function testExceptionWhenUsingFingerscrossedWithoutHandler()
195+
{
196+
$container = new ContainerBuilder();
197+
$loader = new MonologExtension();
198+
199+
$loader->load(array(array('handlers' => array('main' => array('type' => 'fingers_crossed')))), $container);
200+
}
201+
202+
/**
203+
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
204+
*/
205+
public function testExceptionWhenUsingBufferWithoutHandler()
206+
{
207+
$container = new ContainerBuilder();
208+
$loader = new MonologExtension();
209+
210+
$loader->load(array(array('handlers' => array('main' => array('type' => 'buffer')))), $container);
211+
}
212+
213+
/**
214+
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
215+
*/
216+
public function testExceptionWhenUsingServiceWithoutId()
217+
{
218+
$container = new ContainerBuilder();
219+
$loader = new MonologExtension();
220+
221+
$loader->load(array(array('handlers' => array('main' => array('type' => 'service')))), $container);
222+
}
223+
86224
/**
87225
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
88226
*/

0 commit comments

Comments
 (0)