Reputation: 152
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.
Upvotes: 13
Views: 13330
Reputation: 23265
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);
}
}
Upvotes: 7
Reputation: 9085
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.
Upvotes: 6
Reputation: 211
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.
Upvotes: 2
Reputation: 877
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);
}
Upvotes: 15