2013-12-18 3 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 в файл журнала можно включить stacktrace: существует новый метод 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

вы можете даже опустить (строковые) вызовы. По крайней мере, если вы используете Монолог. –

1

getTraceAsString даст вам массив трассировки стека как «конец строки» строку с разделителями. Разверните на 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() возвращает массив, чего хочет Монолог.

+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 
Смежные вопросы