日頃の行い

個人的な日頃の行いをつらつら書いてます\\\\ ٩( 'ω' )و ////

monologで例外のstack traceをいい感じに表示する

普段phpでログを出力するのにmonologを使っていて、
開発時にはdocker-composeでサーバを起動してログを標準出力に出したりしています。
開発時に例外が発生したタイミングでmonolog経由でエラーログを出しているのですが、
stack traceが1行に表示されてしまって見づらかったのでなにかいい方法はないかと調べてみました。
検証に使ったmonologのversionは 1.23.0 です。

monolog

github.com

そしたらこのstack overflowにたどり着いて、なにかのPRにたどり着きました。

stackoverflow.com

github.com

PRのコメントをみたらincludeStacktraces()を呼ぶといいらしいとのことでした。
LineFormatterクラスのメソッドらしいですね。

monolog/LineFormatter.php at 1.23.0 · Seldaek/monolog · GitHub

雑に検証してみました。
コードはこちらです。綺麗さのかけらもないです。
もちろんですが composer install の実行が必要です。
3段階くらい例外がネストしているケースを表示してみました。

monologで例外のstack traceをいい感じに表示する · GitHub

<?php

require_once 'vendor/autoload.php';

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\LineFormatter;

$log1 = new Logger('いい感じにみえないやつ');
$log1->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG));

$log2 = new Logger('いい感じにみえるやつ');
$handler = new StreamHandler('php://stdout', Logger::DEBUG);
$formatter = new LineFormatter();
$formatter->includeStacktraces(true);
$log2->pushHandler($handler->setFormatter($formatter));

function a() {
    throw new \Exception('aaa');
}

function b() {
    try {
        a();
    } catch (\Exception $e) {
        throw new \Exception('bbb', 0, $e);
    }
}

function c() {
    try {
        b();
    } catch (\Exception $e) {
        throw new \Exception('ccc', 0, $e);
    }
}

try {
    c();
} catch (\Exception $e) {
    $log1->error($e);
    $log2->error($e);
}

この状態で実行すると下記のような感じになります。
includeStacktracesを設定していないとstack traceが全て1行に出てしまいますが、
設定していると各行にいい感じに出ているかと思います。
便利。

$php main.php
[2018-03-16 21:23:20] いい感じにみえないやつ.ERROR: Exception: aaa in /Users/a-tanaka/monologphp/main.php:19 Stack trace: #0 /Users/a-tanaka/monologphp/main.php(24): a() #1 /Users/a-tanaka/monologphp/main.php(32): b() #2 /Users/a-tanaka/monologphp/main.php(39): c() #3 {main}  Next Exception: bbb in /Users/a-tanaka/monologphp/main.php:26 Stack trace: #0 /Users/a-tanaka/monologphp/main.php(32): b() #1 /Users/a-tanaka/monologphp/main.php(39): c() #2 {main}  Next Exception: ccc in /Users/a-tanaka/monologphp/main.php:34 Stack trace: #0 /Users/a-tanaka/monologphp/main.php(39): c() #1 {main} [] []
[2018-03-16 21:23:20] いい感じにみえるやつ.ERROR: Exception: aaa in /Users/a-tanaka/monologphp/main.php:19
Stack trace:
#0 /Users/a-tanaka/monologphp/main.php(24): a()
#1 /Users/a-tanaka/monologphp/main.php(32): b()
#2 /Users/a-tanaka/monologphp/main.php(39): c()
#3 {main}

Next Exception: bbb in /Users/a-tanaka/monologphp/main.php:26
Stack trace:
#0 /Users/a-tanaka/monologphp/main.php(32): b()
#1 /Users/a-tanaka/monologphp/main.php(39): c()
#2 {main}

Next Exception: ccc in /Users/a-tanaka/monologphp/main.php:34
Stack trace:
#0 /Users/a-tanaka/monologphp/main.php(39): c()
#1 {main} [] []

まとめ

  • monologのLineFormatterで例外のstack trace表示したいときはincludeStacktracesを設定するといいっぽい