2013-12-18 10 views
32

Io uso Monolog come libreria autonoma nella mia applicazione e recentemente ho riscontrato un problema. Diciamo che, ad un certo punto della mia domanda mi cattura un'eccezione e voglio accedere esso:Registrazione dello stack completo con Monolog

$mylogger->error('Exception caught', array('exception' => $exception)); 

Questo funziona perfettamente tranne una piccola cosa - è non registra tutta traccia dello stack. È possibile registrare la traccia di stack completo dell'eccezione usando i formattatori di compilatori monolog?

risposta

10

No, non è possibile registrare la traccia dello stack utilizzando i formattatori incorporati. Vedi la mia domanda here.

Se si dà un'occhiata a LineFormatter.php si vede che il metodo normalizeException è responsabile per l'acquisizione dei dati di eccezione. Quindi, ho dovuto creare un nuovo formattatore esteso a LineFormatter. Ecco il codice:

<?php 

namespace Monolog\Formatter; 

use Exception; 

class ExceptionLineFormatter extends LineFormatter 
{ 
    protected function normalizeException(Exception $e) 
    { 
     return 'Message: ' . $e->getMessage() . 
       'Stack Trace: '. $e->getTraceAsString(); 
    } 
} 

E io inizializzato il mio logger in questo modo:

$logFile = 'MyLogFile.txt'; 
$handler = new StreamHandler($logFile); 
$handler->setFormatter(new ExceptionLineFormatter); 
$log = new Logger('MyLogger'); 
$handler = self::getStreamHander(); 
$log->pushHandler($handler); 

Questa volontà stamperà il tuo stack trace.

26

In realtà dalla versione 1.12.0 è possibile includere lo stacktrace nel file di registro: è disponibile il nuovo metodochiamato includeStacktraces.

Per utilizzare questo, è necessario sovrascrivere il comportamento predefinito di monologo formattatore:

config.yml

monolog: 
    handlers: 
     main: 
      formatter: your.monolog.service.id 
      (rest of config is as usual) 

services.yml

services: 
    your.monolog.service.id: 
     class: Monolog\Formatter\LineFormatter 
     calls: 
      - [includeStacktraces] 

Controllare github per più info: Pull request

+0

Esiste anche nella JsonFormatter – magnetik

+1

Ho una [risposta separata] (https://stackoverflow.com/a/46379123/1344955) con il codice necessario per utilizzare tale metodo senza un config file. Gli utenti non sono autorizzati a apportare modifiche sostanziali alla risposta di qualcun altro, ma se vuoi modificarlo rimuoverò il mio. – SeinopSys

15

Ho una soluzione molto semplice !!!

$mylogger->error((string) $exception); 
+1

Grazie Amir !!! !!! !!! – adjenks

+0

puoi persino omettere le chiamate (stringa). Almeno se stai usando Monolog. –

1

getTraceAsString vi darà la matrice dello stack come un 'fine linea' stringa delimitata. Esplodi su PHP_EOL e poi foreach attraverso l'array che registra ciascun elemento. Spero che questo ti aiuti.

<?php 
function test() { 
    throw new Exception; 
} 

try { 
    test(); 
} catch(Exception $e) { 
    $array = explode(PHP_EOL, $e->getTraceAsString()); 
    foreach($array as $line){ 
     $mylogger->error($line); 
} 

dovrebbe produrre qualcosa di simile:

#0 index.php(14): test() 
#1 {main} 
1

Questo è come lo faccio, sì anni dopo ...

$mylogger->error('Exception caught', $exception->getTrace());

dal getTrace() restituisce un array, che è ciò che vuole Monolog.

+0

Per chiunque come me che ha usato questo, sii consapevole del fatto che se stai usando un gestore Gelf questo farà un'eccezione. A causa del fatto che l'array getTrace inizia il conteggio a 0, che è una chiave non valida all'interno di 'GelfMessage :: setAdditional()' –

2

Aggiungendo a Tomasz Madeyski's answer, questo è come lo si può utilizzare solo tramite il codice:

use Monolog\Logger; 
use Monolog\Handler\StreamHandler; 
use Monolog\ErrorHandler; 
use Monolog\Formatter\LineFormatter; 

$formatter = new LineFormatter(LineFormatter::SIMPLE_FORMAT, LineFormatter::SIMPLE_DATE); 
$formatter->includeStacktraces(true); // <-- 

$stream = new StreamHandler('error.log'); 
$stream->setFormatter($formatter); 

$logger = new Logger('logger'); 
$logger->pushHandler($stream); 
0

Il Upvoted answer works, ma non si è costretti a creare un servizio personalizzato per questo.

Il monolog.formatter.line esiste già nello stack completo di Symfony 3.4. Si può semplicemente aggiungere una chiamata di metodo su di esso grazie alla CompilerPassInterface:

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 
use Symfony\Component\DependencyInjection\ContainerBuilder; 
use use Symfony\Component\HttpKernel\Kernel; 

class AppKernel extends Kernel implements CompilerPassInterface 
{ 
    public function process(ContainerBuilder $container) 
    { 
     $container->getDefinition('monolog.formatter.line')->addMethodCall('includeStacktraces'); 
    } 
} 

Il gestore monologo non sembra ricevere il servizio di default, in modo da avere ancora specificarlo. Esempio:

monolog: 
    handlers: 
     main: 
      type: rotating_file 
      max_files: 12 
      date_format: 'Y-m' 
      path: '%kernel.logs_dir%/%kernel.environment%.log' 
      level: debug 
      formatter: monolog.formatter.line 
Problemi correlati