web-dev-qa-db-ja.com

Monologで完全なスタックトレースを記録する

アプリケーションでスタンドアロンライブラリとして Monolog を使用していますが、最近問題に遭遇しました。アプリケーションのある時点で例外をキャッチし、それをログに記録したいとしましょう。

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

これは1つの小さなことを除いて完全に機能します。スタックトレース全体をログに記録しません。 monologビルトインフォーマッタを使用して、例外の完全なスタックトレースを記録することは可能ですか?

39
Wild One

実際にバージョン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を確認してください: プルリクエスト

33
Tomasz Madeyski

私は非常に簡単な解決策を持っています!!!

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

いいえ、組み込みフォーマッタを使用してスタックトレースを記録することはできません。私の質問 here をご覧ください。

LineFormatter.phpnormalizeExceptionメソッドが例外データの取得に関与していることがわかります。そのため、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);

これにより、スタックトレースが出力されます。

10
Rayhan Muktader

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);
6
SeinopSys

単に設定ファイル(Symfony Bundle)を "include_stacktraces"パラメーターとともに使用できます:

monolog:
    handlers:
        main:
            type: stream
            path: "%kernel.logs_dir%/%kernel.environment%.log"
            level: info
            channels: ["!event"]
            max_files: 10
            include_stacktraces: true <--- SET TO TRUE

@ seeこのコミット

@ see完全なスキーマ(構成)

4
kxo

そうです、そうです、数年後...

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

getTrace()は配列を返すため、Monologはそれを望んでいます。

2
adjenks

スタックトレースを記録したい場合only例外がスローされたときに、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ごとに使用できるようになります。

1
eithed

getTraceAsStringは、スタックトレース配列を「行末」で区切られた文字列として提供します。 PHP_EOLで展開し、各要素を記録する配列を介してforeachします。お役に立てれば。

<?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}
0
php_bob

pvoted 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ハンドラーはデフォルトでサービスを受信して​​いないようですので、指定する必要があります。例:

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
0
Soullivaneuh