8000 [Debug] Better error handling · symfony/symfony@4d60d08 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4d60d08

Browse files
committed
[Debug] Better error handling
1. Send the raw exception in the log context instead of custom formatting 2. Add config option to log in Symfony all PHP errors
1 parent 904279e commit 4d60d08

File tree

12 files changed

+380
-214
lines changed

12 files changed

+380
-214
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ public function getConfigTreeBuilder()
116116
$this->addPropertyAccessSection($rootNode);
117117
$this->addPropertyInfoSection($rootNode);
118118
$this->addCacheSection($rootNode);
119+
$this->addPhpErrorsSection($rootNode);
119120

120121
return $treeBuilder;
121122
}
@@ -692,4 +693,38 @@ private function addCacheSection(ArrayNodeDefinition $rootNode)
692693
->end()
693694
;
694695
}
696+
697+
private function addPhpErrorsSection(ArrayNodeDefinition $rootNode)
698+
{
699+
$rootNode
700+
->children()
701+
->arrayNode('php_errors')
702+
->info('PHP errors handling configuration')
703+
->addDefaultsIfNotSet()
704+
->children()
705+
->booleanNode('log')
706+
->info('Use the app logger instead of the PHP logger for logging PHP errors.')
707+
->defaultValue($this->debug)
708+
->treatNullLike($this->debug)
709+
->end()
710+
->booleanNode('throw')
711+
->info('Throw PHP errors as \ErrorException instances.')
712+
->defaultValue($this->debug)
713+
->treatNullLike($this->debug)
714+
->end()
715+
->booleanNode('scream')
716+
->info('Force logging of @-silenced errors.')
717+
->defaultValue($this->debug)
718+
->treatNullLike($this->debug)
719+
->end()
720+
->booleanNode('scope')
721+
->info('Catch local variables when logging/throwing PHP errors.')
722+
->defaultValue($this->debug)
723+
->treatNullLike($this->debug)
724+
->end()
725+
->end()
726+
->end()
727+
->end()
728+
;
729+
}
695730
}

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

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ public function load(array $configs, ContainerBuilder $container)
131131
$this->registerProfilerConfiguration($config['profiler'], $container, $loader);
132132
$this->registerCacheConfiguration($config['cache'], $container);
133133
$this->registerWorkflowConfiguration($config['workflows'], $container, $loader);
134+
$this->registerDebugConfiguration($config['php_errors'], $container, $loader);
134135

135136
if ($this->isConfigEnabled($container, $config['router'])) {
136137
$this->registerRouterConfiguration($config['router'], $container, $loader);
@@ -147,27 +148,6 @@ public function load(array $configs, ContainerBuilder $container)
147148
$this->registerPropertyInfoConfiguration($config['property_info'], $container, $loader);
148149
}
149150

150-
$loader->load('debug_prod.xml');
151-
$definition = $container->findDefinition('debug.debug_handlers_listener');
152-
153-
if ($container->hasParameter('templating.helper.code.file_link_format')) {
154-
$definition->replaceArgument(5, '%templating.helper.code.file_link_format%');
155-
}
156-
157-
if ($container->getParameter('kernel.debug')) {
158-
$definition->replaceArgument(2, E_ALL & ~(E_COMPILE_ERROR | E_PARSE | E_ERROR | E_CORE_ERROR | E_RECOVERABLE_ERROR));
159-
160-
$loader->load('debug.xml');
161-
162-
// replace the regular event_dispatcher service with the debug one
163-
$definition = $container->findDefinition('event_dispatcher');
164-
$definition->setPublic(false);
165-
$container->setDefinition('debug.event_dispatcher.parent', $definition);
166-
$container->setAlias('event_dispatcher', 'debug.event_dispatcher');
167-
} else {
168-
$definition->replaceArgument(1, null);
169-
}
170-
171151
$this->addAnnotatedClassesToCompile(array(
172152
'**Bundle\\Controller\\',
173153
'**Bundle\\Entity\\',
@@ -417,6 +397,46 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde
417397
}
418398
}
419399

400+
/**
401+
* Loads the debug configuration.
402+
*
403+
* @param array $config A php errors configuration array
404+
* @param ContainerBuilder $container A ContainerBuilder instance
405+
* @param XmlFileLoader $loader An XmlFileLoader instance
406+
*/
407+
private function registerDebugConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
408+
{
409+
$loader->load('debug_prod.xml');
410+
411+
if ($container->getParameter('kernel.debug')) {
412+
$loader->load('debug.xml');
413+
414+
// replace the regular event_dispatcher service with the debug one
415+
$definition = $container->findDefinition('event_dispatcher');
416+
$definition->setPublic(false);
417+
$container->setDefinition('debug.event_dispatcher.parent', $definition);
418+
$container->setAlias('event_dispatcher', 'debug.event_dispatcher');
419+
}
420+
421+
$definition = $container->findDefinition('debug.debug_handlers_listener');
422+
423+
if (!$config['log']) {
424+
$definition->replaceArgument(1, null);
425+
}
426+
427+
if (!$config['throw']) {
428+
$container->setParameter('debug.error_handler.throw_at', 0);
429+
}
430+
431+
$definition->replaceArgument(4, $config['scream']);
432+
433+
if ($container->hasParameter('templating.helper.code.file_link_format')) {
434+
$definition->replaceArgument(5, '%templating.helper.code.file_link_format%');
435+
}
436+
437+
$definition->replaceArgument(6, $config['scope']);
438+
}
439+
420440
/**
421441
* Loads the router configuration.
422442
*

src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
<parameters>
88
<parameter key="debug.container.dump">%kernel.cache_dir%/%kernel.container_class%.xml</parameter>
9-
<parameter key="debug.error_handler.throw_at">-1</parameter>
109
</parameters>
1110

1211
<services>

src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
66

77
<parameters>
8-
<parameter key="debug.error_handler.throw_at">0</parameter>
8+
<parameter key="debug.error_handler.throw_at">-1</parameter>
99
</parameters>
1010

1111
<services>
@@ -14,10 +14,11 @@
1414
<tag name="monolog.logger" channel="php" />
1515
<argument>null</argument><!-- Exception handler -->
1616
<argument type="service" id="logger" on-invalid="null" />
17-
<argument>null</argument><!-- Log levels map for enabled error levels -->
18-
<argument>null</argument>
17+
<argument>-1</argument><!-- Log levels map for enabled error levels -->
18+
<argument>%debug.error_handler.throw_at%</argument>
1919
<argument>true</argument>
2020
<argument>null</argument><!-- %templating.helper.code.file_link_format% -->
21+
<argument>true</argument>
2122
</service>
2223

2324
<service id="debug.stopwatch" class="Symfony\Component\Stopwatch\Stopwatch" />

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,12 @@ protected static function getBundleDefaultConfig()
274274
'default_redis_provider' => 'redis://localhost',
275275
),
276276
'workflows' => array(),
277+
'php_errors' => array(
278+
'log' => true,
279+
'throw' => true,
280+
'scream' => true,
281+
'scope' => true,
282+
),
277283
);
278284
}
279285
}

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
{% if collector.counterrors or collector.countdeprecations or collector.countscreams %}
77
{% set icon %}
88
{% set status_color = collector.counterrors ? 'red' : collector.countdeprecations ? 'yellow' : '' %}
9-
{% set error_count = collector.counterrors + collector.countdeprecations + collector.countscreams %}
9+
{% set error_count = collector.counterrors + collector.countdeprecations %}
1010
{{ include('@WebProfiler/Icon/logger.svg') }}
1111
<span class="sf-toolbar-value">{{ error_count }}</span>
1212
{% endset %}
@@ -55,7 +55,7 @@
5555
{# sort collected logs in groups #}
5656
{% set deprecation_logs, debug_logs, info_and_error_logs, silenced_logs = [], [], [], [] %}
5757
{% for log in collector.logs %}
58-
{% if log.context.level is defined and log.context.type is defined and log.context.type in [constant('E_DEPRECATED'), constant('E_USER_DEPRECATED')] %}
58+
{% if log.context.errorCount is defined and log.context.type is defined and log.context.type in ['E_DEPRECATED', 'E_USER_DEPRECATED'] %}
5959
{% set deprecation_logs = deprecation_logs|merge([log]) %}
6060
{% elseif log.context.scream is defined and log.context.scream == true %}
6161
{% set silenced_logs = silenced_logs|merge([log]) %}
@@ -170,21 +170,22 @@
170170
{% macro render_log_message(category, log_index, log, is_deprecation = false) %}
171171
{{ log.message }}
172172

173+
{% if log.context.errorCount is defined and log.context.errorCount > 1 %}
174+
<span class="text-small text-bold">({{ log.context.errorCount }} times)</span>
175+
{% endif %}
176+
173177
{% if is_deprecation %}
174-
{% set stack = log.context.stack|default([]) %}
175-
{% set stack_id = 'sf-call-stack-' ~ category ~ '-' ~ log_index %}
178+
{% set trace = log.context.trace|default([]) %}
179+
{% set trace_id = 'sf-call-trace-' ~ category ~ '-' ~ log_index %}
176180

177-
{% if log.context.errorCount is defined %}
178-
<span class="text-small text-bold">({{ log.context.errorCount }} times)</span>
179-
{% endif %}
180181

181-
{% if stack %}
182-
<button class="btn-link text-small sf-toggle" data-toggle-selector="#{{ stack_id }}" data-toggle-alt-content="Hide stack trace">Show stack trace</button>
182+
{% if trace %}
183+
<button class="btn-link text-small sf-toggle" data-toggle-selector="#{{ trace_id }}" data-toggle-alt-content="Hide trace trace">Show trace trace</button>
183184
{% endif %}
184185

185-
{% for index, call in stack if index > 1 %}
186+
{% for index, call in trace if index > 1 %}
186187
{% if index == 2 %}
187-
<ul class="sf-call-stack hidden" id="{{ stack_id }}">
188+
<ul class="sf-call-trace hidden" id="{{ trace_id }}">
188189
{% endif %}
189190

190191
{% if call.class is defined %}
@@ -206,7 +207,7 @@
206207
{% endif %}
207208
</li>
208209

209-
{% if index == stack|length - 1 %}
210+
{% if index == trace|length - 1 %}
210211
</ul>
211212
{% endif %}
212213
{% endfor %}
@@ -224,7 +225,7 @@
224225
<a class="btn-link text-small sf-toggle" data-toggle-selector="#{{ context_id }}" data-toggle-alt-content="Hide full context">Show full context</a>
225226

226227
<div id="{{ context_id }}" class="context">
227-
<pre>{{ context_dump }}</pre>
228+
{{ dump(log.context) }}
228229
</div>
229230
{% else %}
230231
{{ context_dump }}

0 commit comments

Comments
 (0)
0