😸

Laravel SQLログを別ファイルに出力する

2023/02/15に公開

SQLのログを出力するチェネルの設定を作る

config/logging.phpに設定を書く

        // SQLクエリのログチャンネル
        'sqlQueryLog' => [
            'driver' => 'custom',
            'via' => App\Logging\CreateSqlQueryLogger::class,
            'path' => storage_path('logs/sql.log'),
            'level' => 'debug',  // ログレベル debug 以上だけ出力
            'days' => 7,        // 7日分のログを保持する
        ],

SQLクエリ用Monologインスタンスの生成とログの書き込み

$config には、config/logging.php で sqlQueryLog に設定した値が連想配列で入ってきます。

<?php

namespace App\Logging;

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

class CreateSqlQueryLogger
{
    /**
     * SQLクエリ用Monologインスタンス生成
     * @param  array  $config
     * @return \Monolog\Logger
     */
    public function __invoke(array $config)
    {

        // 引数の $config には、config/logging.php で sqlQueryLog に設定した値が連想配列で入ってくる
        /* 
          'sqlQueryLog' => [
            'driver' => 'custom',
            'via' => App\Logging\CreateSqlQueryLogger::class,
            'path' => storage_path('logs/sql.log'),
            'level' => 'debug',  // ログレベル debug 以上だけ出力
            'days' => 7,        // 7日分のログを保持する
        ], 
        */

        // 'debug'とかの文字列をMonologが使えるログレベルに変換
        $level = Logger::toMonologLevel($config['level']);

        // 日ごとにログローテートするハンドラ作成
        $hander = new RotatingFileHandler($config['path'], $config['days'], $level);  

        // 改行コードを出力する&カラのコンテキストを出力しないフォーマッタを設定
        $hander->setFormatter(new LineFormatter(null, null, true, true));

        // Monologインスタンス作成してハンドラ設定して返却
        $logger = new Logger('SQL');  // ロガー名は 'SQL' にした。これはログに出力される
        $logger->pushHandler($hander);
        return $logger;
    }
}

AppServiceProviderに登録

アプリケーション全体で利用したいので、AppServiceProviderに登録
config/logging.phpでログの出力設定の有無をできるようにしておく。

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        // クエリーイベントのリッスン
        \DB::listen(function($query) {

            // コンフィグでSQLログを出力する設定
            if (config('logging.sql.enable') !== true) {
                return;
            }

            // ログに出力するクエリーのログをまとめる
            $queryLog = $query->time.' ms -> '.' SQL: '.$query->sql;
            if ($query->bindings) {
                $queryLog .= "\n".'bindings: '.var_export($query->bindings, true);
            }
            
            // sqlQueryLogのチャンネルでSQLを別のログファイルに出力する
            \Log::channel('sqlQueryLog')->debug($queryLog);
        });
    }
}

まとめ

SQLのログファイルを別にする場合

  1. config/logging.phpに、SQLログ出力設定を書く
  2. SQLクエリ用のMonologの生成と処理をクラスファイルを作る
  3. AppServiceProviderに登録する

Discussion