Question

Why errors from console tasks are not logged. For example Exception on php warning:

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

I see what printed in stdout, but nothing logged to logs. (I use console commands in cron). In web these exceptions logged with backtrace, which in this situation is more informational than just this exception.

As a solution: I enclose all process function in try..catch block and log the backtrace manually.

Is anyone know how to enable or configure logging in console tasks. I think it must be somewhere.

Was it helpful?

Solution

As I followed the code, there's actually no such an option to enable logging for commands. In app/console is this code:

use Symfony\Bundle\FrameworkBundle\Console\Application;

...

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

It calls Symfony\Component\Console\Application::run() in which there's try/catch block. On exception method renderException() is called, but no logging happens anywhere.

Also note that app/console always by default exits with error code on exception.

You can create you own Application class extending Symfony\Bundle\FrameworkBundle\Console\Application and modify app/console to use it. Than you can override run() method and add errors logging.

Or you can modify just app/console and handle erros like this:

// $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);
}

OTHER TIPS

If that's the matter of simply understanding what went wrong where, you can run your app with the verbose flag -v or --verbose, which will automatically print the exception trace on the screen.

TL;DR : just use this bundle

From the cookbook :

To get your console application to automatically log uncaught exceptions for all of your commands, you can use console events.

Create a service tagged as an event listener for the console.exception event :

# services.yml
services:
    kernel.listener.command_dispatch:
    class: Acme\DemoBundle\EventListener\ConsoleExceptionListener
    arguments:
        logger: "@logger"
    tags:
        - { name: kernel.event_listener, event: console.exception }

You can now do whatever you want with console exceptions :

<?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);
    }
}

Another way is to implement your own custom OutputInterface class and override the writeln method to log the error there. Then use the new class when you execute the run() method.

This way you can adhere to the Open/Close Principle of Symfony without having to modify the base classes and still achieve your goals.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top