Symfony 2 Регистрация исключений в консоли
Почему ошибки из консольных задач не регистрируются. Например исключение на php предупреждение:
[ErrorException]
Notice: Undefined offset: 1 in /var/www/project/vendor/doctrine/lib/Doctrine/ORM/Query.php line 298
Я вижу, что напечатано в stdout,но ничего не записано в журналы. (Я использую консольные команды в cron). В web эти исключения регистрируются с помощью backtrace, что в данной ситуации является более информативным, чем просто это исключение.
В качестве решения: я заключаю всю функцию процесса в try..поймайте блок и протоколируйте обратный путь вручную.
Кто-нибудь знает, как включить или настроить вход в консольные задачи. Я думаю, он должен быть где-то.
4 ответа:
Поскольку я следовал коду, на самом деле нет такой опции, чтобы включить ведение журнала для команд. В
app/console
есть такой код:use Symfony\Bundle\FrameworkBundle\Console\Application; ... $application = new Application($kernel); $application->run();
Он вызывает
Symfony\Component\Console\Application::run()
, в котором есть блок try/catch. При исключении вызывается методrenderException()
, но нигде не происходит протоколирования.Также обратите внимание, что
app/console
всегда по умолчанию завершает работу с кодом ошибки при исключении.Вы можете создать свой собственный
Application
класс extendingSymfony\Bundle\FrameworkBundle\Console\Application
и изменитьapp/console
, чтобы использовать его. Чем можно переопределить методrun()
и добавить ошибки лесозаготовительный.Или вы можете изменить просто
app/console
и обрабатывать erros следующим образом:// $application->run(); $application->setCatchExceptions(false); try { $output = new Symfony\Component\Console\Output\ConsoleOutput(); $application->run(null, $output); } catch (Exception $e) { ... error logging ... $application->renderException($e, $output); $statusCode = $e->getCode(); $statusCode = is_numeric($statusCode) && $statusCode ? $statusCode : 1; exit($statusCode); }
Если это вопрос простого понимания того, что пошло не так, где, вы можете запустить свое приложение с подробным флагом
-v
или--verbose
, который будет автоматически печатать трассировку исключений на экране.
TL; DR : просто используйте этот пучок
Чтобы заставить консольное приложение автоматически регистрировать необработанные исключения для всех ваших команд, вы можете использовать события консоли.
Создайте службу, помеченную как прослушиватель событий для события
console.exception
:# services.yml services: kernel.listener.command_dispatch: class: Acme\DemoBundle\EventListener\ConsoleExceptionListener arguments: logger: "@logger" tags: - { name: kernel.event_listener, event: console.exception }
Теперь вы можете делать все, что хотите, с консольными исключениями:
<?php // src/Acme/DemoBundle/EventListener/ConsoleExceptionListener.php namespace Acme\DemoBundle\EventListener; use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Psr\Log\LoggerInterface; class ConsoleExceptionListener { private $logger; public function __construct(LoggerInterface $logger) { $this->logger = $logger; } public function onConsoleException(ConsoleExceptionEvent $event) { $command = $event->getCommand(); $exception = $event->getException(); $message = sprintf( '%s: %s (uncaught exception) at %s line %s while running console command `%s`', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine(), $command->getName() ); $this->logger->error($message); } }
Другой способ-реализовать свой собственный пользовательский класс
OutputInterface
и переопределить методwriteln
для регистрации ошибки. Затем используйте новый класс при выполнении методаrun()
.Таким образом, Вы можете придерживаться принципа Open/Close Symfony без необходимости изменять базовые классы и все равно достигать своих целей.