2013-12-18 5 views
32

Ich verwende Monolog als eigenständige Bibliothek in meiner Anwendung und vor kurzem stieß ich auf ein Problem. Lassen Sie uns sagen, an einem gewissen Punkt in meiner Anwendung ich eine Ausnahme zu fangen und ich möchte es protokollieren:Logging vollen Stack-Trace mit Monolog

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

Das perfekt bis auf eine winzige Ding funktioniert - es ist nicht ganze Stack-Trace anmeldet. Ist es möglich, den vollständigen Stack-Trace der Ausnahme mithilfe von integrierten Monolog-Formatierern zu protokollieren?

Antwort

10

Nein, Sie können den Stack-Trace nicht mithilfe der integrierten Formatierer protokollieren. Siehe meine Frage here.

Wenn Sie einen Blick auf LineFormatter.php werfen, sehen Sie, dass die normalizeException Methode für das Ergreifen der Ausnahmedaten verantwortlich ist. Also musste ich einen neuen Formatierer erstellen, der LineFormatter erweitert. Hier ist der Code:

<?php 

namespace Monolog\Formatter; 

use Exception; 

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

Und ich initialisiert meinen Logger wie so:

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

Dies wird Ihren Stack-Trace ausdrucken.

26

Eigentlich seit Version 1.12.0 ist es möglich, StackTrace in Ihre Protokolldatei aufzunehmen: Es gibt eine neue Methode LineFormatter namens includeStacktraces.

Um dies zu nutzen, müssen Sie das Standardverhalten von Monolog Formatierer zu überschreiben:

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] 

prüfen Github für mehr info: Pull request

+0

Es existiert auch in den JsonFormatter – magnetik

+1

Ich habe eine [separate Antwort] (https://stackoverflow.com/a/46379123/1344955) mit dem Code hinzugefügt benötigt ohne Config das Verfahren zu verwenden, Datei. Benutzer dürfen keine wesentlichen Änderungen an der Antwort anderer Personen vornehmen, aber wenn Sie sie bearbeiten möchten, entferne ich meine. – SeinopSys

15

Ich habe eine sehr einfache Lösung !!!

+1

Danke Amir !!! !!! !!! – adjenks

+0

können Sie sogar (Zeichenfolge) Anrufe weglassen. Zumindest wenn du Monolog benutzt. –

1

getTraceAsString gibt Ihnen das Stack-Trace-Array als Begrenzungszeichen am Ende der Zeile. Explode auf PHP_EOL und dann foreach durch das Array jedes Element protokolliert. Hoffe das hilft.

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

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

sollte wie folgt produzieren:

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

Dies ist, wie ich es tun, später ja Jahre ...

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

seit getTrace() ein Array zurückgibt, Was Monolog will.

+0

Für jemanden wie mich, der dies verwendet, sollte man bedenken, dass wenn man einen Gelf-Handler verwendet, dies eine Ausnahme auslöst. Aufgrund der Tatsache, dass das getTrace-Array beginnt, bei 0 zu zählen, was ein ungültiger Schlüssel innerhalb der 'GelfMessage :: setAdditional()' ist –

2

Hinzufügen zu Tomasz Madeyski's answer, das ist, wie Sie es über Code verwenden können, nur:

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

Die Upvoted answer works, aber Sie sind nicht einen benutzerdefinierten Dienst dafür zu schaffen gezwungen.

Die monolog.formatter.line existiert bereits auf Symfony 3.4 full stack. Sie können einfach einen Methodenaufruf auf sie dank der CompilerPassInterface hinzufügen:

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'); 
    } 
} 

Der Monolog Handler scheint nicht den Dienst standardmäßig zu erhalten, so dass Sie es noch nicht festlegen. Beispiel:

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