Symfony 2在控制台中记录异常

时间:2012-02-16 07:54:50

标签: php logging symfony console-application error-logging

为什么不记录来自控制台任务的错误。 例如关于php警告的例外:

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

我看到stdout中打印的内容,但没有记录到日志中。 (我在cron中使用控制台命令)。 在Web中,这些异常使用backtrace记录,在这种情况下,这种异常比仅此异常更具信息性。

作为解决方案:我将所有过程函数包含在try..catch块中并手动记录回溯。

是否有人知道如何在控制台任务中启用或配置日志记录。 我认为它一定是某个地方。

4 个答案:

答案 0 :(得分:15)

当我遵循代码时,实际上没有这样的选项来启用命令的日志记录。在app/console中是这段代码:

use Symfony\Bundle\FrameworkBundle\Console\Application;

...

$application = new Application($kernel);
$application->run();

它会调用Symfony\Component\Console\Application::run(),其中包含try / catch块。在调用异常方法renderException()时,但在任何地方都不会记录日志。

另请注意,app/console始终默认退出,并在异常时退出错误代码。

您可以创建自己的ApplicationSymfony\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);
}

答案 1 :(得分:6)

TL; DR :只需使用this bundle

来自cookbook

  

要让您的控制台应用程序自动记录所有命令的未捕获异常,您可以使用控制台事件。

创建标记为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 :(得分:6)

如果只是简单地了解哪里出了问题,您可以使用详细标记-v--verbose运行您的应用,屏幕上将automatically print the exception trace

答案 3 :(得分:2)

另一种方法是实现自己的自定义OutputInterface类并覆盖writeln方法以在那里记录错误。然后在执行run()方法时使用新类。

通过这种方式,您可以遵守Symfony的Open/Close Principle,而无需修改基类并仍能实现目标。