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

Skip to content

Commit 8f24549

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 cf30750 commit 8f24549

File tree

13 files changed

+373
-215
lines changed

13 files changed

+373
-215
lines changed

UPGRADE-4.0.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,12 @@ FrameworkBundle
117117
* The `framework.serializer.cache` option and the services
118118
`serializer.mapping.cache.apc` and `serializer.mapping.cache.doctrine.apc`
119119
have been removed. APCu should now be automatically used when available.
120-
120+
121121
* The `Controller::getUser()` method has been removed in favor of the ability
122122
to typehint the security user object in the action.
123123

124+
* The default value of the `framework.php_errors.log` configuration key is set to true.
125+
124126
HttpKernel
125127
----------
126128

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

Lines changed: 25 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,28 @@ 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(false)
708+
->treatNullLike(false)
709+
->end()
710+
->booleanNode('throw')
711+
->info('Throw PHP errors as \ErrorException instances.')
712+
->defaultValue($this->debug)
713+
->treatNullLike($this->debug)
714+
->end()
715+
->end()
716+
->end()
717+
->end()
718+
;
719+
}
695720
}

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

Lines changed: 43 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,48 @@ 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+
$debug = $container->getParameter('kernel.debug');
412+
413+
if ($debug) {
414+
$loader->load('debug.xml');
415+
416+
// replace the regular event_dispatcher service with the debug one
417+
$definition = $container->findDefinition('event_dispatcher');
418+
$definition->setPublic(false);
419+
$container->setDefinition('debug.event_dispatcher.parent', $definition);
420+
$container->setAlias('event_dispatcher', 'debug.event_dispatcher');
421+
}
422+
423+
$definition = $container->findDefinition('debug.debug_handlers_listener');
424+
425+
if (!$config['log']) {
426+
$definition->replaceArgument(1, null);
427+
}
428+
429+
if (!$config['throw']) {
430+
$container->setParameter('debug.error_handler.throw_at', 0);
431+
}
432+
433+
$definition->replaceArgument(4, $debug);
434+
435+
if ($container->hasParameter('templating.helper.code.file_link_format')) {
436+
$definition->replaceArgument(5, '%templating.helper.code.file_link_format%');
437+
}
438+
439+
$definition->replaceArgument(6, $debug);
440+
}
441+
420442
/**
421443
* Loads the router configuration.
422444
*

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=< 1241 span class="pl-pds">"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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ protected static function getBundleDefaultConfig()
274274
'default_redis_provider' => 'redis://localhost',
275275
),
276276
'workflows' => array(),
277+
'php_errors' => array(
278+
'log' => false,
279+
'throw' => true,
280+
),
277281
);
278282
}
279283
}

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 stack trace">Show stack 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