Обработка ошибок PHP в производстве с помощью веб-сайта на основе Symfony 2
Мы запускаем несколько веб-сайтов symfony2 в производстве, и мы используем как Airbrake, так и Sentry для сбора исключений. Реальные исключения хорошо работают даже в рабочей среде, мы можем регистрировать их с большим количеством контекста, и мы можем показать пользователю красивую страницу с 500 ошибками.
Ошибки PHP - это совсем другая история. Я могу зарегистрировать их в Sentry, используя обработчик "при выключении", но, используя его, я не могу передать много контекста. Для пользователя также существует только пустая ошибка 503. Это отстой потому что мы не можем показать пользователю "следующий" шаг на случай, если что-то пошло не так.
Исходя из фона Java, мне очень нравятся "реальные" исключения, и в режиме разработки есть класс, который преобразует множество ошибок в исключения, но нет документированного или очевидного способа включить это в производство, поэтому я думаю, что, возможно, мне не стоит больше спрашивать;)
Как вы, ребята, справляетесь с этим, и какое это влечет за собой снижение производительности?
Это перекрестный пост от: http://groups.google.com/group/symfony2/browse_thread/thread/6129f57a35d8cb90?hl=en
4 answers
- вы должны обрабатывать все свои "ошибки" как исключения
- вы должны отправить правильный код заголовка http и перехватить эти коды ошибок http на веб-сервере: http://wiki.nginx.org/HttpFastcgiModule#fastcgi_intercept_errors (в apache тоже есть что-то подобное)
- обработчик завершения работы вам нужен только для регистрации "фатальных" вещей
- "контекст" в "функции выключения" не ограничен (если вы "выделяете" его до ошибки!)
- Лучшая оптимизация - это не делать ошибки;)
Способ PHP включить это:
-
Ошибки (начальная загрузка!):
set_error_handler('errorToException'); function errorToException($code, $message, $file = null, $line = 0) { if (error_reporting() == 0) { return true; } throw new \ErrorException($message, $code, $file, $line); }
-
Исключения (класс обработчика исключений):
set_exception_handler(array($this, 'exception')); public function exception(\Exception $e) { $this->logger->log($e); }
-
Неустранимые ошибки (класс обработчика исключений):
register_shutdown_function(array($this, 'shutdown')); public function shutdown() { $error = error_get_last(); if (isset($error)) { $this->exception(new \FatalException($error['message'], $error['type'], $error['file'], $error['line'])); } }
Это -PHP-путь™. Вся ваша обработка ошибок "Symfony2™" должна оставаться прежней.
В Symfony2 мы можем ввести службу прослушивания ошибок/исключений (которая улавливает все ошибки), а в onKernelException() мы можем включить всю логику нашего домена для обработки ошибок/исключений.
Предполагая, что вы используете по крайней мере Symfony 2.3, существует новый механизм.
use Symfony\Component\Debug\ErrorHandler;
require_once __DIR__.'/../app/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';
// we need to register the Error Handler in order
// to get fatal errors delivered as Exceptions
ErrorHandler::register();
[...]
Вы можете добавить обработчик событий к некоторым событиям ядра (исключение, onResponse ....)