Laravel で、エラーログを JSON で出力しつつ Stack trace を含めたい

要約

Monolog\Formatter\JsonFormatter を拡張したクラスを作り、それを使う。

メモ

前提

  • アプリケーションは Laravel
  • AWS の ECS で Cloudwatch Logs へ送信する
  • Log Driver は awslogs
  • エラーログに Stack trace も含めたい

この前提だと、デフォルトの LineFormatter では Stack trace が行ごとに分割されてしまう。
なので JSON で 1 行にフォーマットして出力する。

方法

まず JsonFormatter を継承し、コンストラクタで includeStacktraces メソッドを実行するだけのクラスを作る。

# app/Logging/Formatter/CustomJsonFormatter.php

<?php

declare(strict_types=1);

namespace App\Logging\Formatter;

use Monolog\Formatter\JsonFormatter;

class CustomJsonFormatter extends JsonFormatter
{
    /**
     * @param int $batchMode
     * @param bool $appendNewline
     */
    public function __construct($batchMode = self::BATCH_MODE_JSON, $appendNewline = true)
    {
        parent::__construct($batchMode, $appendNewline);
        $this->includeStacktraces();
    }
}

次にログの設定で formatter に指定する。

# config/logging.php 抜粋

'channels' => [
    'stderr' => [
        'driver' => 'monolog',
        'handler' => Monolog\Handler\StreamHandler::class,
        'formatter' => App\Logging\Formatter\CustomJsonFormatter::class,
        'with' => [
            'stream' => 'php://stderr',
        ],
    ],

余談1

  • Symfony では MonologBundle を使えば解決らしい
    • 良いなぁ

余談2