2012-02-16 18 views
11

Perché gli errori dalle attività della console non vengono registrati. Per esempio un'eccezione in allarme php:Symfony 2 Eccezioni di registrazione nella console

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

vedo quello stampato in stdout, ma nulla registrato in registri. (Io uso i comandi della console in cron). Nel web queste eccezioni sono registrate con backtrace, che in questa situazione è più informativo di questa eccezione.

Come soluzione: accludo tutte le funzioni di processo nel blocco try..catch e registra manualmente il backtrace.

Qualcuno sa come abilitare o configurare la registrazione nelle attività della console. Penso che debba essere da qualche parte.

risposta

14

Come ho seguito il codice, in realtà non esiste un'opzione per abilitare la registrazione dei comandi. In app/console è questo codice:

use Symfony\Bundle\FrameworkBundle\Console\Application; 

... 

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

Chiede Symfony\Component\Console\Application::run() in cui non c'è provare blocco/catch. Il metodo di eccezione renderException() viene chiamato, ma nessuna registrazione avviene ovunque.

Si noti inoltre che app/console si chiude sempre per impostazione predefinita con codice di errore su eccezione.

È possibile creare la propria classe Application che si estende Symfony\Bundle\FrameworkBundle\Console\Application e modificare app/console per utilizzarla. Quindi è possibile sostituire il metodo run() e aggiungere la registrazione degli errori.

Oppure si può modificare solo app/console e gestire erros come questo:

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

Grazie per la spiegazione. Scavo nella console dei file di avvio e index.php, ma dovrei scavare più a fondo nella classe Application. Ma sembra che le classi di applicazioni in web e console condividano lo stesso comportamento. – Sawered

2

Un altro modo è quello di implementare la propria classe personalizzata OutputInterface 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 allo Open/Close Principle di Symfony senza dover modificare le classi di base e raggiungere comunque i propri obiettivi.

6

TL; DR: basta usare this bundle

Dal cookbook:

per ottenere la vostra applicazione 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); 
    } 
} 
+0

Sì, poiché Symfony 2.3 questa è una soluzione migliore. – Martin

6

Se questo è il dato di semplicemente capire cosa è andato storto dove, è possibile eseguire l'app con la bandiera dettagliata -v o --verbose, che sarà automatically print the exception trace sullo schermo.

+0

Hai ragione, ma la domanda riguardava la scrittura di errori da registrare (per esempio nel file) E 'stato necessario quando eseguo comandi cli da cron – Sawered

+0

Vero, mi dispiace, ho mancato la parte cron. Non riuscivo a capire come arrivare al backtrace senza complicarlo troppo, deciso a condividere i risultati. –

+1

@IanBytchek, grazie comunque, la tua risposta mi ha aiutato molto! –