Laravel(Monolog)日志传递可选自定义参数的实现问题
Laravel 8 自定义Monolog MySQL处理器添加可选Domain ID参数方案
核心思路
利用Monolog的context参数传递可选的domain_id,同时修改数据库表和处理器代码,将domain_id存入单独字段,方便后续检索。
步骤1:修正日志调用方式
Laravel日志方法的第二个参数要求是关联数组(即context),需把domain_id放在数组中传递:
// 带domain_id的日志 Log::info("New record created for domain", ['domain_id' => $domain_id]); // 不带domain_id的常规日志不受影响 Log::info("System initialization completed");
步骤2:更新数据库表结构
给log_entries表添加可选的domain_id字段(允许为null),通过迁移实现:
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class AddDomainIdToLogEntriesTable extends Migration { public function up() { Schema::table('log_entries', function (Blueprint $table) { $table->unsignedBigInteger('domain_id')->nullable()->after('message'); // 可选:添加索引提升检索速度 $table->index('domain_id'); }); } public function down() { Schema::table('log_entries', function (Blueprint $table) { $table->dropIndex(['domain_id']); $table->dropColumn('domain_id'); }); } }
执行迁移:
php artisan migrate
步骤3:修改自定义MySQL处理器
在MySQLLoggingHandler的write方法中,从$record['context']提取domain_id并存入数据库:
namespace App\Logging; use DB; use Illuminate\Support\Facades\Auth; use Monolog\Logger; use Monolog\Handler\AbstractProcessingHandler; class MySQLLoggingHandler extends AbstractProcessingHandler{ public function __construct($level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); } protected function write(array $record):void { $remote_addr = $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1'; $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown'; $data = array( 'message' => $record['message'], 'domain_id' => $record['context']['domain_id'] ?? null, // 新增提取domain_id的逻辑 'context' => json_encode($record['context']), 'level' => $record['level'], 'level_name' => $record['level_name'], 'channel' => $record['channel'], 'record_datetime' => $record['datetime']->format('Y-m-d H:i:s'), 'extra' => json_encode($record['extra']), 'formatted' => $record['formatted'], 'remote_addr' => $remote_addr, 'user_agent' => $user_agent, 'created_at' => date("Y-m-d H:i:s"), ); DB::connection()->table('log_entries')->insert($data); } }
这里用PHP 8的??空合并运算符简化了空值判断,同时保留原有context的存储,不影响其他上下文数据的记录。
效果验证
现在可以直接通过domain_id字段快速检索对应日志:
// 查询某个domain的所有日志 $logs = DB::table('log_entries')->where('domain_id', 123)->get();
内容的提问来源于stack exchange,提问作者Mr Fett
相关产品推荐
相关产品推荐

