Symfony 2 Регистрация исключений в консоли - PullRequest
13 голосов
/ 16 февраля 2012

Почему ошибки из консольных задач не регистрируются. Например, Исключение при предупреждении php:

[ErrorException]<br> Notice: Undefined offset: 1 in /var/www/project/vendor/doctrine/lib/Doctrine/ORM/Query.php line 298

Я вижу, что напечатано в stdout, но в журналах ничего не записано. (Я использую консольные команды в cron). В сети эти исключения регистрируются с помощью backtrace, который в этой ситуации более информативен, чем просто это исключение.

Как решение: я включаю все функции процесса в блок try..catch и вручную регистрирую обратную трассировку.

Кто-нибудь знает, как включить или настроить ведение журнала в консольных задачах. Я думаю, что это должно быть где-то.

Ответы [ 4 ]

15 голосов
/ 16 февраля 2012

Поскольку я следовал коду, на самом деле нет такой опции, чтобы включить ведение журнала для команд.В 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 расширение класса Symfony\Bundle\FrameworkBundle\Console\Application и изменение app/console для его использования.Чем вы можете переопределить метод run() и добавить регистрацию ошибок.

Или вы можете изменить просто app/console и обрабатывать ошибки следующим образом:

// $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);
}
6 голосов
/ 08 января 2015

Если вам нужно просто понять, что пошло не так, вы можете запустить свое приложение с подробным флагом -v или --verbose, который автоматически выведет на экран трассировку исключения .

6 голосов
/ 28 апреля 2014

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);
    }
}
2 голосов
/ 20 декабря 2012

Другой способ - реализовать свой собственный класс OutputInterface и переопределить метод writeln, чтобы зарегистрировать ошибку там. Затем используйте новый класс при выполнении метода run().

Таким образом, вы можете придерживаться принципа открытия / закрытия Symfony без необходимости изменять базовые классы и при этом достигать своих целей.

...