Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Debug] generic ErrorHandler#10921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

@nicolas-grekas
Copy link
Member

QA
Bug fix?no
New feature?yes
BC breaks?minor, see updated tests
Deprecations?yes
Tests pass?yes
Fixed ticketsnone
LicenseMIT
Doc PRnone

The proposed goal of this PR is to build a class that can serve as a foundation for a standard error handler, shared with other projects and not only used by the FrameworkBundle.

This is a merge of my previous work on the subject (https://github.com/nicolas-grekas/Patchwork/blob/master/core/logger/class/Patchwork/PHP/InDepthErrorHandler.php) and recent improvements of error handling in Symfony's Debug\ErrorHandler.

ErrorHandler is introduced, which provides five bit fields that control how errors are handled:

  • thrownErrors: errors thrown as ContextErrorException
  • loggedErrors: logged errors, when not @-silenced
  • scopedErrors: errors thrown or logged with their local context
  • tracedErrors: errors logged with their trace, only once for repeated errors
  • screamedErrors: never @-silenced errors

Each error level can be logged by a dedicated PSR-3 logger object.
Screaming only applies to logging.
Throwing takes precedence over logging.
Uncaught exceptions are logged as E_ERROR.
E_DEPRECATED and E_USER_DEPRECATED levels never throw.
E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw.
Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so.
As errors have a performance cost, repeated errors are all logged, so that the developer
can see them and weight them as more important to fix than others of the same level.

  • build a more generic ErrorHandler
  • update service/listeners definitions to take advantage of the new interface of ErrorHandler
  • add phpdocs
  • add tests

@gnugat
Copy link
Contributor

Wow! You've putted a lot of effort to document your work, which is great!

@nicolas-grekas
Copy link
MemberAuthor

I just updated ErrorHandler to take advantage of UniversalErrorHandler.
Tests pass, with some slight updates/BC breaks. Please tell me if this is affordable or not.
Fatal error handling is still in ErrorHandler and needs "universalization", but at least for other kind of errors, this hopefully demonstrates the "Universal" prefix.
Convincing?

@wouterj
Copy link
Member

Tests pass, with some slight updates/BC breaks. Please tell me if the is affordable or not.

As long as you stick tohttp://symfony.com/bc all is fine :)

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Removing this line is the most severe BC break that this patch does: the deprecation logger is now going to receive a more standardized context as second argument (type, file, line, trace, level). So the change is about renamingstack totrace and having type's value set to E_DEPRECATED or E_USER_DEPRECATED, not self::TYPE_DEPRECATION anymore.
To me, this special const was a hack, so removing it is a good thing (c).

@mvrhov
Copy link

Just came close to the functionality provided by tracy and I'll switch back both the dev and prod error handlers.

@nicolas-grekas
Copy link
MemberAuthor

Uncaught exceptions, OOM and other fatal errors are now handled thanks to#10941 and updates in UniversalErrorHandler. I'm quite ok with the way things a "universalized" now, but that needs reviews. Feedback welcomed.

I'll now work on reconfiguring Symfony for taking advantage of UniversalErrorHandler (last commit is a WIP).

But I have a question: I'm not comfortable with the 3 monolog channels Symfony currently has (emergency, deprecation, scream). I'd prefer having only one for php-errors. But then, should I preserve BC, ie map the old channels somewhere?

The UniversalErrorHandler is currently able to have one different logger/channel per error level, just to cope with Symfony's way of logging errors. But I'm not sure this is a best practice, so I'd prefer removing this possibility, if that's a Good Thing. Is it?

ping@Tobion@Seldaek ?

@stof
Copy link
Member

@nicolas-grekas using a separate channel for deprecations was the way found to integrate deprecations in the profiler AFAIK.

@Seldaek
Copy link
Member

IMO emergency makes no sense because that could be on the main app channel or something with a log level set to EMERGENCY. deprecation it's good to keep it separated, and scream I am not quite sure what it is, errors that have an @ but scream was enabled or ..?

@nicolas-grekas
Copy link
MemberAuthor

@stof it maybe was the intention, but if I read the code correctly, channel information is lost during data collection, so the code relies on a side effect, based on$log['context']['type'] === ErrorHandler::TYPE_DEPRECATION. A loose test that works but doesn't require any specific channel.
In short, the deprecation channel is not used at all.
@Seldaek you guessed, scream is for ignoring @.
From your comments, I suggest having only one channel, so that if someone wants to send php errors somewhere, they can be isolated, being an emergency, a deprecation or any other, silenced or not.

@lyrixx
Copy link
Member

I'd prefer having only one for php-errors. But then, should I preserve BC, ie map the old channels somewhere?

Having N logger has a cost. So i'm 👎 to have a logger per php-errors by default. But indeed, if it's configurable (in a PHP way) it could be perfect.

@nicolas-grekasnicolas-grekas changed the title[WIP] [Debug] UniversalErrorHandler[RFR] [Debug] UniversalErrorHandlerMay 21, 2014
@nicolas-grekas
Copy link
MemberAuthor

I pushed a new iteration, the PR is ready for review, please comment.

Thanks for your feedback@lyrixx, with this PR, you should be able to plug e.g. Sentry by service configuration, no need to statically ErrorHandler::setLogger() directly anymore:
I plugged the new error handler in symfony by adding a singlephp channel, some XML and FrameworkExtension updates, with more flexible options (I believe).

@nicolas-grekasnicolas-grekas changed the title[RFR] [Debug] UniversalErrorHandler[RFR] [Debug] generic ErrorHandlerMay 22, 2014
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

currently, FrameworkBundle does not depend on psr/log in its composer.json. but this makes it required now (while the optional logger in some classes does not). You need to update the composer.json to require psr/log in the standalone bundle (the fullstack package already depends on psr/log)

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Fixed

@nicolas-grekas
Copy link
MemberAuthor

I just discovered that something is missing since a long time in the configuration of the prod environment for error handling: theErrorsLoggersListener does aErrorHandler::setLogger(), butErrorHandler::register() is never called, so no logging can ever happen, except the one done by the native PHP handler.

This led me to two points:

  • I think we should always callErrorHandler::register(), and useset_error_handler()'s second argument to catch only what we want to catch (thus no perf impact in prod).
  • Does Symfony have recommended settings forlog_errors anderror_log ini settings? Because IMHO it could be a good idea to put native php logs inapp/logs/,if the settings are not configured.

Also, I updated the behavior of the proposed error handler for E_RECOVERABLE_ERROR and E_USER_ERROR levels: these levels are special in that they are considered fatal by the native PHP error handler, even when @-silenced. Thus, the only viable option for a user error handler is to always throw an exception for these two types, no matter the error_reporting() level nor anything else.
This strategy ensures that code paths are correct, but also that the application can continue if it decides to handle the exception.

This special behavior is an other argument for always registering the error handler, even and especially in the prod env.

@nicolas-grekasnicolas-grekas changed the title[RFR] [Debug] generic ErrorHandler[Debug] generic ErrorHandlerJun 4, 2014
@nicolas-grekas
Copy link
MemberAuthor

This PR is ready for review/merge IMHO.
Any 👍 from deciders/mergers?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

a private property does not need deprecated. It can be removed directly as there is no BC concern for private stuff

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I prefer keeping the@deprecated notice because that will make easier to spot where code is to be removed when moving to 3.0.
I can't remove this private right now since it's used in a deprecated method.

@nicolas-grekas
Copy link
MemberAuthor

I just merged AbstractExceptionHandler back into ExceptionHandler.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

why are you changing the visibility ?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Good catch, I missed telling about that: I think that we should open more custom use of the ExceptionHandler. The failSafeHandle() is the right hooking point. It's a more lightweight version of the previous AbstractExceptionHandler.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

sendPhpResponse() andcreateResponse() are public, so there is already a way to change the way this method works.

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I just removed the private failSafeHandle completely and replaced it by a call to sendPhpResponse().
Still ok for you?

@stof
Copy link
Member

except for the visibility change, I'm 👍

@romainneutron
Copy link
Contributor

I'm 👍 on the ErrorHandler changes, I'm pretty confident that changes in the framework glue have been carefully reviewed by@stof

@romainneutron
Copy link
Contributor

Good to me 👍

@nicolas-grekasnicolas-grekas merged commit1701447 intosymfony:masterJun 16, 2014
nicolas-grekas added a commit that referenced this pull requestJun 16, 2014
This PR was merged into the 2.6-dev branch.Discussion----------[Debug] generic ErrorHandler| Q             | A| ------------- | ---| Bug fix?      | no| New feature?  | yes| BC breaks?    | minor, see updated tests| Deprecations? | yes| Tests pass?   | yes| Fixed tickets | none| License       | MIT| Doc PR        | noneThe proposed goal of this PR is to build a class that can serve as a foundation for a standard error handler, shared with other projects and not only used by the FrameworkBundle.This is a merge of my previous work on the subject (https://github.com/nicolas-grekas/Patchwork-Error-Logger/blob/master/class/Patchwork/PHP/InDepthErrorHandler.php) and recent improvements of error handling in Symfony's Debug\ErrorHandler.ExceptionHandler has a new AbstractExceptionHandler base class that factors out the handling of fatal errors casted to exceptions.ErrorHandler is introduced, which provides five bit fields that control how errors are handled:- thrownErrors: errors thrown as ContextErrorException- loggedErrors: logged errors, when not @-silenced- scopedErrors: errors thrown or logged with their local context- tracedErrors: errors logged with their trace, only once for repeated errors- screamedErrors: never @-silenced errorsEach error level can be logged by a dedicated PSR-3 logger object.Screaming only applies to logging.Throwing takes precedence over logging.Uncaught exceptions are logged as E_ERROR.E_DEPRECATED and E_USER_DEPRECATED levels never throw.E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw.Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so.As errors have a performance cost, repeated errors are all logged, so that the developercan see them and weight them as more important to fix than others of the same level.- [x] build a more generic ErrorHandler- [x] update service/listeners definitions to take advantage of the new interface of ErrorHandler- [x] add phpdocs- [x] add testsCommits-------1701447 [Debug] update FrameworkBundle and HttpKernel for new ErrorHandler839e9ac [Debug] generalized ErrorHandler
@romainneutron
Copy link
Contributor

First merge 👏

@nicolas-grekasnicolas-grekas deleted the universal-error-handler branchJune 16, 2014 14:05
@nicolas-grekas
Copy link
MemberAuthor

It's your turn now@romainneutron ! Let's help@fabpot scale with Symfony :)

@benbor
Copy link

Hi@nicolas-grekas
I tried to throw an exception even for E_USER_DEPRECATED errors, but couldn't do it.

ErrorHandler::register()->throwAt(E_ALL,true);

I started to debug ErrorHandler and found this PR. I see you made the following changes

E_DEPRECATED and E_USER_DEPRECATED levels never throw.

But I really don't understand why? Could you please explain this point, or get me some post about it?
Big thanks :)

@nicolas-grekas
Copy link
MemberAuthor

nicolas-grekas commentedOct 18, 2018
edited
Loading

Because a deprecation should never break the execution flow: they are just notices you can ignore - and you should log if you don't want to.

@benbor
Copy link

Thank you,@nicolas-grekas for your faster reaction.
But I have an idea, I want to break the execution flow for not production environment. I want to force clear code. If I make PR which extends the behavior and will throw Error even for E_DEPRECATED it will be useful?

publicfunctionthrowAt($levels,$replace =false,$ignoreDeprecated =true){$prev =$this->thrownErrors;$this->thrownErrors = ($levels |E_RECOVERABLE_ERROR |E_USER_ERROR);if ($ignoreDeprecated) {$this->thrownErrors &= ~E_USER_DEPRECATED & ~E_DEPRECATED;     }//...}

I will not change behavior by default, but allow to use the wondeful feature of see that errors while development.
WDYT?
Thanks

@nicolas-grekas
Copy link
MemberAuthor

nicolas-grekas commentedOct 18, 2018
edited
Loading

I don't think that's the appropriate place to do so.
If you want to enforce your devs to fix deprecations, you should use the phpunit-bridge in your CI instead.

*/
privatefunctionreRegister($prev)
{
if ($prev !==$this->thrownErrors |$this->loggedErrors) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Sorry to be so late, but isn't there an operator precedence bug here?https://3v4l.org/UmbJk

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Looks like so! Please send a fix, branch 4.4

guilliamxavier reacted with thumbs up emoji
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Submitted#47100

nicolas-grekas added a commit that referenced this pull requestJul 28, 2022
…avier)This PR was squashed before being merged into the 4.4 branch.Discussion----------[Debug][ErrorHandler] fix operator precedence| Q             | A| ------------- | ---| Branch?       | 4.4| Bug fix?      | yes| New feature?  | no| Deprecations? | no| Tickets       |Fix#10921 (comment)| License       | MITBut I'm struggling to come up with a *failing* test scenario :/ if the bug is only causing evaluating the condition as truthy instead of false when `$prev` is already equal to `$this->thrownErrors | $this->loggedErrors`, I guess it will just re-register the same, without real visible effect?Commits-------7f68914 [Debug][ErrorHandler] fix operator precedence
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

1 more reviewer

@guilliamxavierguilliamxavierguilliamxavier left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Labels

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

11 participants

@nicolas-grekas@gnugat@wouterj@mvrhov@stof@Seldaek@lyrixx@romainneutron@benbor@fabpot@guilliamxavier

[8]ページ先頭

©2009-2025 Movatter.jp