如何根据debug状态开启或关闭Laravel日志的上下文附加数据
如何根据debug状态开启或关闭Laravel日志的上下文附加数据
我来帮你解决这个问题!你遇到的情况是因为withoutContext()的作用范围和你想控制的全局上下文不是一回事——withoutContext()只能清除日志实例的本地上下文(也就是你通过Log::withContext()手动添加的内容),而框架自动附加的是全局ContextRepository里的元数据,这部分是通过日志管理器的处理器注入的,所以你的原有代码没法生效。
下面给你两种可行的解决方案,选哪种都能实现需求:
方案一:自定义日志格式化器(推荐,更符合Laravel配置风格)
这种方法通过自定义格式化器,根据debug状态动态决定是否保留全局上下文数据:
- 创建自定义格式化器类
在app/Logging目录下新建CustomDnsFormatter.php(如果没有Logging目录就自己创建):
<?php namespace App\Logging; use Illuminate\Log\ContextRepository; use Monolog\Formatter\LineFormatter; class CustomDnsFormatter extends LineFormatter { public function format(array $record): string { // 当debug为false时,移除extra中的全局上下文数据 if (!config('app.debug')) { $globalContext = app(ContextRepository::class)->all(); foreach (array_keys($globalContext) as $key) { unset($record['extra'][$key]); } } return parent::format($record); } }
- 配置日志通道使用自定义格式化器
打开config/logging.php,找到你的dns通道配置,添加formatter指定我们刚创建的类:
'dns' => [ 'driver' => 'single', // 你的通道驱动,可能是single/daily等 'path' => storage_path('logs/dns.log'), 'level' => 'debug', 'formatter' => App\Logging\CustomDnsFormatter::class, // 新增这一行 ],
- 简化你的业务代码
现在不需要在代码里判断debug状态了,直接使用日志通道即可:
public function __construct() { $this->r = new ResultMsg(); $this->r->msgPrefix = "POWERDNSSERVICE: "; $this->log = Log::channel('dns'); // 直接用通道,格式化器会自动处理 $this->logException = Log::channel('dns_exception'); }
方案二:通过服务提供者动态修改日志处理器
如果你不想修改格式化器,也可以在服务提供者中动态为日志通道添加处理器,过滤上下文数据:
在App\Providers\AppServiceProvider.php的boot方法中添加以下代码:
use Illuminate\Log\ContextRepository; use Illuminate\Log\LogManager; use Monolog\Processor\ProcessorInterface; public function boot() { $this->app->extend(LogManager::class, function (LogManager $logManager) { // 针对dns通道进行修改 $logManager->extend('dns', function ($app, $config) use ($logManager) { // 获取原本的dns通道实例 $logger = $logManager->resolve($config); // 如果debug为false,添加处理器移除全局上下文 if (!config('app.debug')) { $logger->pushProcessor(new class implements ProcessorInterface { public function __invoke(array $record): array { $globalContext = app(ContextRepository::class)->all(); foreach (array_keys($globalContext) as $key) { unset($record['extra'][$key]); } return $record; } }); } return $logger; }); return $logManager; }); }
之后同样可以直接在业务代码中使用Log::channel('dns'),处理器会根据debug状态自动处理上下文数据。
备注:内容来源于stack exchange,提问作者Lem
相关产品推荐
相关产品推荐

