Handler d'erreurs global
QuietGuard\Monitor\ErrorHandler branche les handlers globaux de PHP afin qu'un hôte PHP simple, sans pipeline d'exceptions de framework, remonte tout de même les erreurs non capturées. Les frameworks (Laravel, Symfony) ont leurs propres hooks et ne doivent pas l'appeler.
Enregistrement
ErrorHandler::register() est un unique appel statique qui prend un Reporter configuré :
Appelez-le une fois, le plus tôt possible dans votre bootstrap, après la construction du Reporter.
Ce qu'il enregistre
register() câble trois hooks globaux :
set_exception_handler, toutThrowablenon capturé est envoyé via$reporter->reportException($e). Le handler chaîne : si un autre handler d'exceptions global était enregistré avantErrorHandler::register(), il s'exécute toujours après que l'exception a été remontée (le monitoring remonte d'abord, puis délègue). En l'absence de handler précédent, l'exception (message, fichier:ligne et stack trace) est écrite danserror_log, à l'identique de ce que le comportement par défaut de PHP aurait consigné : installer le monitoring ne supprime donc jamais la trace locale du crash côté hôte.set_error_handler, une erreur PHP levée est encapsulée dans uneErrorExceptionpuis remontée, à condition que sa sévérité atteigne le plancher décrit plus bas. Il vérifie d'aborderror_reporting() & $severity, de sorte que les valeurs supprimées par@ou en dessous du niveauerror_reportingcourant sont ignorées. Il renvoie ensuitefalsepour que la gestion d'erreurs normale de PHP s'exécute quand même.register_shutdown_function, à l'arrêt,error_get_last()est inspecté et, s'il s'agit d'un type fatal (E_ERROR,E_PARSE,E_CORE_ERROR,E_COMPILE_ERROR), uneErrorExceptionest remontée. Cela capture les fatales que le handler d'erreurs ne peut pas intercepter.
Tous les chemins passent par le Reporter, qui ne lève jamais d'exception : enregistrer ces handlers ne peut donc pas casser l'hôte.
Le plancher de sévérité, et le plafond qui va avec
register() prend deux arguments optionnels :
Par défaut, seules E_USER_ERROR et E_RECOVERABLE_ERROR sont remontées. Toute sévérité était auparavant transmise, en un POST synchrone chacune, sans plancher, sans dédoublonnage et sans plafond : un seul E_WARNING dans une boucle sur cinq cents lignes, c'était cinq cents appels HTTP bloquants dans un chargement de page, ce qui se lit comme une panne pour le visiteur et brûle le quota mensuel d'un forfait gratuit en une journée.
Les vraies fatales sont absentes du défaut exprès. PHP n'appelle aucun handler d'erreurs utilisateur pour E_ERROR, E_PARSE, E_CORE_ERROR ni E_COMPILE_ERROR, et c'est la fonction d'arrêt ci-dessus qui les attrape déjà. Ce que le défaut conserve, c'est la paire qu'un hôte lève vraiment et qu'il pense : une fatale applicative, et une erreur de type que PHP a laissé passer.
Deux garde-fous s'appliquent quel que soit le masque :
- un rapport par site et par requête : la même erreur levée cent fois sur le même
fichier:ligneest un seul fait, et les quatre-vingt-dix-neuf autres POST sont la latence de l'application hôte, pas la vôtre à dépenser ; - un plafond de
$maxPerRequest, 20 par défaut, parce qu'un masque ne voit pas une boucle : cinquante lignes distinctes passent n'importe quel plancher et restent cinquante requêtes.
Passez le masque explicitement pour l'élargir, en connaissance de cause :
Un bootstrap PHP minimal
Le SDK Laravel et le bundle Symfony n'utilisent pasErrorHandler: chacun branche le pipeline d'exceptions de son framework. Le plugin WordPress, lui, l'utilise, WordPress n'ayant pas de pipeline d'exceptions à lui, et prend le plancher par défaut. RéservezErrorHandlerà un hôte dépourvu de son propre pipeline d'exceptions.
Vous lisez la documentation PHP Core v1.0.