2012-02-16 11 views
11

Dlaczego błędy z zadań konsoli nie są rejestrowane. Na przykład Wyjątek na ostrzeżenia php:Symfony 2 Rejestrowanie wyjątków w konsoli

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

widzę co drukowane w stdout, ale nic zalogowany do logów. (Używam poleceń konsoli w cron). W sieci te wyjątki są rejestrowane za pomocą śledzenia wstecznego, które w tej sytuacji jest bardziej informacyjne niż tylko ten wyjątek.

Jako rozwiązanie: Załączam całą funkcję procesu w bloku try..catch i ręcznie rejestruję śledzenie.

Czy ktoś wie, jak włączyć lub skonfigurować rejestrowanie w zadaniach konsoli. Myślę, że to musi być gdzieś.

Odpowiedz

14

Tak jak postępowałem zgodnie z kodem, w rzeczywistości nie ma takiej opcji, aby włączyć rejestrowanie poleceń. W app/console jest ten kod:

use Symfony\Bundle\FrameworkBundle\Console\Application; 

... 

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

Apeluje Symfony\Component\Console\Application::run() w którym istnieje try/catch bloku. Wyjątkiem jest metoda renderException(), ale nigdzie nie następuje rejestrowanie.

Należy również pamiętać, że app/console zawsze domyślnie kończy działanie z kodem błędu w przypadku wyjątku.

Możesz utworzyć własną klasę Application rozszerzającą Symfony\Bundle\FrameworkBundle\Console\Application i modyfikując app/console, aby z niej skorzystać. Następnie można zastąpić metodę run() i dodać rejestrowanie błędów.

Albo można modyfikować tylko app/console i obsługiwać erros takie jak ten:

// $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

Dzięki za wyjaśnienie. Zajmuję się uruchamianiem plików console & index.php, ale powinienem zagłębić się w klasie Application. Wygląda jednak na to, że klasy aplikacji w sieci i konsoli mają takie samo działanie. – Sawered

2

Innym sposobem jest wprowadzenie własnego niestandardowego OutputInterface klasę i zastąpić metodę writeln do logowania błąd istnieje. Następnie użyj nowej klasy podczas wykonywania metody run().

W ten sposób można przystąpić do Symfony Open/Close Principle bez konieczności modyfikowania klas bazowych i nadal osiągnąć swoje cele.

6

TL; DR: wystarczy użyć this bundle

Z cookbook:

Aby otrzymać aplikację konsoli do automatycznego logowania niezłapane wyjątki dla wszystkich poleceń, można użyć zdarzenia konsoli.

Utwórz usługę oznaczony jako detektora zdarzeń dla zdarzenia 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 } 

Teraz możesz robić, co chcesz z wyjątkami konsoli:

<?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

Tak, ponieważ Symfony 2.3 jest to lepsze rozwiązanie. – Martin

6

Jeśli to kwestia po prostu zrozumienie, co poszło nie tak, gdzie możesz uruchomić swoją aplikację z pełną flagą: -v lub --verbose, która wyświetli się na ekranie na automatically print the exception trace.

+0

Masz rację, ale pytanie dotyczyło zapisywania błędów w logowaniu (np. W pliku). Było to konieczne, gdy uruchamiam polecenia cli z cron – Sawered

+0

Prawda, przepraszam, brakowało części cron. Nie mogłem wymyślić, jak dostać się do śladu, nie komplikując go zbyt wiele, postanowił podzielić się wynikami. –

+1

@IanBytchek, dziękuję i tak, twoja odpowiedź bardzo mi pomogła! –