Symfony 2 eccezioni di registrazione in console
-
25-10-2019 - |
Domanda
Perché gli errori da attività della console non è registrato. Per esempio un'eccezione in allarme php:
[ErrorException]
Notice: Undefined offset: 1 in /var/www/project/vendor/doctrine/lib/Doctrine/ORM/Query.php line 298
I vedere cosa stampata in stdout, ma nulla registrato in registri. (Io uso i comandi della console in cron). In queste eccezioni web registrati con backtrace, che in questa situazione è più informativo che solo questa eccezione.
Come soluzione: Allego tutte le funzioni di processo in try..catch blocco e il login backtrace manualmente
.È qualcuno sa come abilitare o Configura registrazione in attività della console. Penso che deve essere da qualche parte.
Soluzione
Mentre seguivo il codice, non c'è in realtà alcuna tale opzione per attivare la registrazione per i comandi. In app/console
è questo codice:
use Symfony\Bundle\FrameworkBundle\Console\Application;
...
$application = new Application($kernel);
$application->run();
Si chiama Symfony\Component\Console\Application::run()
in cui non c'è blocco try / catch. Su eccezione metodo renderException()
viene chiamato, ma non la registrazione avviene da nessuna parte.
Si noti inoltre che app/console
sempre da uscite di default con il codice di errore eccezione.
È possibile creare voi propria classe Application
estendere Symfony\Bundle\FrameworkBundle\Console\Application
e modificare app/console
di usarlo. Che è possibile ignorare il metodo run()
e aggiungere gli errori di registrazione.
In alternativa, è possibile modificare solo app/console
e maniglia erros in questo modo:
// $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);
}
Altri suggerimenti
Se questo è il tratta semplicemente di capire cosa è andato storto, dove, è possibile eseguire la vostra applicazione con il verbose bandierina -v
o --verbose
, che sarà stampare automaticamente l'eccezione traccia sullo schermo.
TL; DR : basta usare questo bundle
Per ottenere l'applicazione di console per accedere automaticamente le eccezioni non gestite fanno per tutti i tuoi comandi, è possibile utilizzare gli eventi della console.
Creare un servizio etichettato come un listener di eventi per l'evento 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 }
È ora possibile fare quello che vuoi con le eccezioni della console:
<?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);
}
}
Un altro modo è quello di implementare la propria classe OutputInterface
costume e l'override del metodo writeln
per registrare l'errore c'è. Quindi utilizzare la nuova classe quando si esegue il metodo run()
.
In questo modo è possibile aderire alla Open / Close Principio di Symfony, senza dover modificare le classi base e ancora raggiungere i vostri obiettivi.