[PHP][Laravel] Laravelでログをカスタムしてタイムゾーン日時、ユーザーID、クラス名などの様々な情報を出力したい

バージョン

Laravel 5.7

概要

Laravelのログ機能を拡張して、UTCJSTの時刻、IPアドレス、呼び出し元クラス名・メソッド名、 ユーザーIDを出力する。
なお、PHP側のタイムゾーンUTCとする。

Laravelは5.6からログ出力方法が変わったのでそれ以前のバージョンの場合はここをコピペでは使えないかも。

コード

■config\logging.php
今回はdailyに対してログの設定をする

    'channels' => [
        'stack' => [
            'driver' => 'stack',
            'channels' => 'daily',
        ],

        'daily' => [
            'driver' => 'daily',
            // tapに拡張クラスを指定する
            'tap' => [App\Logging\CustomizeFormatter::class],
            'path' => storage_path('logs/laravel.log'),
            'level' => 'debug',
            'days' => 31,
        ],

■App\Logging\CustomizeFormatter.php
ログ出力時に呼ばれる

<?php

namespace App\Logging;

use Monolog\Formatter\LineFormatter;
use Monolog\Logger;
use Monolog\Processor\IntrospectionProcessor;
use Monolog\Processor\WebProcessor;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;

class CustomizeFormatter
{
    /**
     * ログフォーマット
     */
    private $logFormat = '[(UTC)%datetime% (JST)%extra.localdate%][ID:%extra.userid%][%extra.ip%][%extra.class%@%extra.function%(%extra.line%)][%level_name%] %message% %context%' . PHP_EOL;

    /**
     * 日付フォーマット
     */
    private $dateFormat = 'Y-m-d H:i:s.v';

    /**
     * Customize the given logger instance.
     *
     * @param  \Illuminate\Log\Logger  $logger
     * @return void
     */
    public function __invoke($logger)
    {
        // formatter
        $formatter = new LineFormatter($this->logFormat, $this->dateFormat, true, true);

        // extra(class,method)
        $ip = new IntrospectionProcessor(Logger::DEBUG, ['Illuminate\\']);

        // ip address
        $wp = new WebProcessor();

        foreach ($logger->getHandlers() as $handler) {
            $handler->setFormatter($formatter);
            $handler->pushProcessor($ip);
            $handler->pushProcessor($wp);
            $handler->pushProcessor([$this, 'processLogRecord']);
        }
    }

    /**
     * edit record data
     *
     * @return array
     */
    public function processLogRecord(array $record): array
    {
        $userid = 'ログインしていない';
        if (Auth::check()) {
            $userid = Auth::id();
        }

        $record['extra'] += [
            'userid' => $userid,
            'localdate' => Carbon::now('JST')
        ];
        return $record;
    }
}

■呼び出し元コントローラー HogeController.php

        \Log::debug("デバッグログです");

■出力ログ内容

[(UTC)2019-07-30 14:40:27.076 (JST)2019-07-30 23:40:27.079][ID:1234][192.168.1.10][App\Http\Controllers\HogeController@showForm(83)][DEBUG] デバッグログです 

ユーザに紐づくタイムゾーンを出したい場合はprocessLogRecordメソッドで
ユーザのタイムゾーンを取得して、変換すれば良い。

ログの細かな仕様は公式サイトで確認を。 ログ 5.7 Laravel