2013-12-18 35 views
32

我在我的應用程序中使用Monolog作爲獨立庫,最近我遇到了一個問題。比方說,在我的應用程序某些時候我趕上一個例外,我想記錄它:使用Monolog記錄完整堆棧跟蹤

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

這工作完全只是一件小事情 - 它不記錄整個堆棧跟蹤。是否有可能使用monolog內置格式化程序記錄異常的完整堆棧跟蹤?

回答

10

不,您不能使用內置格式化程序記錄堆棧跟蹤。看到我的問題here

如果你看看LineFormatter.php,你會發現normalizeException方法負責抓取異常數據。所以,我不得不創建一個新的格式化程序,它擴展了LineFormatter。下面的代碼:

<?php 

namespace Monolog\Formatter; 

use Exception; 

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

我初始化我的記錄,像這樣:

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

這將打印出您的堆棧跟蹤。

26

實際上,由於版本1.12.0有可能在您的日誌文件中包含堆棧跟蹤:LineFormatter有一個新方法,稱爲includeStacktraces

要使用此,你需要重寫獨白格式的默認行爲:

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] 

檢查github上更多info: Pull request

+0

它還與使用所述方法,無需一個配置所需的代碼存在於JsonFormatter – magnetik

+1

我添加了一個[單獨的應答(https://stackoverflow.com/a/46379123/1344955)文件。用戶不允許對其他人的答案進行實質性編輯,但如果您想編輯它,我將刪除我的答案。 – SeinopSys

15

我有一個非常簡單的解決方案!

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

謝謝阿米爾! !!! !!! – adjenks

+0

你甚至可以忽略(字符串)調用。至少如果你使用Monolog。 –

1

getTraceAsString會爲您提供Stack Trace數組作爲'End of Line'分隔字符串。在PHP_EOL上展開,然後通過數組記錄每個元素。希望這可以幫助。

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

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

應該產生這樣的:

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

這是我要做的事,是年後...

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

因爲getTrace()返回一個數組,這是Monolog想要的。

+0

對於像我這樣使用過的人來說,要注意的事實是,如果你使用Gelf處理程序,這會引發異常。由於getTrace數組從0開始計數,這是'GelfMessage :: setAdditional()'中的無效鍵, –

2

添加到Tomasz Madeyski's answer,這是你怎麼能僅通過代碼中使用它:

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

Upvoted answer works,但你不會被強迫創建一個定製服務。

monolog.formatter.line已經存在Symfony 3.4全堆棧。你可以簡單地在其上添加感謝一個方法調用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'); 
    } 
} 

的獨白處理程序似乎並不在默認情況下接收服務,所以你還是要指定它。例如:

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 
相關問題