使用Monolog记录完整堆栈跟踪

时间:2013-12-18 11:46:14

标签: php monolog

我在我的应用程序中使用Monolog作为独立库,最近我遇到了一个问题。让我们说,在我的应用程序中的某个时刻,我遇到一个异常,我想记录它:

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

除了一件小事之外,它的工作方式非常完美 - 它不会记录整个堆栈跟踪。是否可以使用monolog内置格式化程序记录异常的完整堆栈跟踪?

9 个答案:

答案 0 :(得分:31)

实际上,自版本1.12.0以来,可以在您的日志文件中包含堆栈跟踪:LineFormatter的新方法称为includeStacktraces

要使用此功能,您需要覆盖monolog格式化程序的默认行为:

<强> 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以获取更多信息: Pull request

答案 1 :(得分:16)

我有一个非常简单的解决方案!!!

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

答案 2 :(得分: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);

这将打印出你的堆栈跟踪。

答案 3 :(得分:6)

添加到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);

答案 4 :(得分:2)

我就是这样做的,多年以后......

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

因为getTrace()返回一个数组,这是Monolog想要的。

答案 5 :(得分:1)

getTraceAsString将为您提供Stack Trace数组作为&#39; End of Line&#39;分隔字符串。在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}

答案 6 :(得分:1)

如果您想在抛出异常时仅记录stacktrace ,您可以在AppServiceProvider中执行此操作:

public function register()
{
     $logger = Log::getMonolog();
     $logger->pushProcessor(function ($record) {
        if (isset($record['context']['exception']))
        {
            $record['extra']['stacktrace'] = $record['context']['exception']->getTraceAsString();
        }

        return $record;
    });
}

这会将堆栈跟踪添加到extra列,然后可以按LineFormatter使用

答案 7 :(得分:1)

您可以简单地将配置文件(Symfony捆绑包)与“ include_stacktraces ”参数一起使用:

<WebView Source="{Binding UrlToGoTo}"  HeightRequest= "300" WidthRequest="250" Navigated="Handle_Navigated" VerticalOptions="FillAndExpand" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" />

@see this commit

@see the full schema (configuration)

答案 8 :(得分:0)

Upvoted answer works,但您不必为此创建自定义服务。

Symfony 3.4完整堆栈上已存在monolog.formatter.line。由于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处理程序似乎没有收到服务,因此您仍然需要指定它。例如:

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