Laravel如何向Google Stackdriver日志注入自定义进程ID?
我来帮你搞定这个问题!你遇到的核心问题是:你的stackdriver日志通道没有应用ProcessorTap处理逻辑,而你只在本地的single通道里配置了tap。下面分步骤给你解决方案:
原因分析
Laravel的tap配置是用来在日志实例初始化后,对其进行额外修改的机制。但你当前的stackdriver通道是通过custom驱动+CreateStackdriverLogger类手动创建Monolog实例的,而且没有给这个通道添加tap配置,所以你的PID处理器根本没作用在Stackdriver的日志链路上。另外,Stackdriver使用的PsrHandler会把日志转发到Google的PSR日志客户端,Monolog的LineFormatter对它来说是无效的(Google会自己处理日志格式),但你添加到extra或context里的PID会被保留并发送到Google日志服务。
方案一:给Stackdriver通道添加Tap配置
这是最贴合你现有代码结构的方案:
1. 更新config/logging.php的Stackdriver通道
给stackdriver数组加上tap配置,让Laravel初始化这个通道时应用你的处理器:
'stackdriver' => [ 'driver' => 'custom', 'via' => App\Logging\CreateStackdriverLogger::class, 'level' => 'debug', 'tap' => [App\Logging\ProcessorTap::class], // 新增这一行 ],
2. 调整ProcessorTap.php适配Stackdriver
因为Stackdriver不需要Monolog的LineFormatter,我们可以给处理器加个判断,只给本地日志通道设置格式,避免无效操作:
namespace App\Logging; use Illuminate\Log\Logger; use Illuminate\Support\Arr; use Monolog\Formatter\LineFormatter; use Monolog\Handler\StreamHandler; // 导入StreamHandler类 class ProcessorTap { public function __invoke($logger) { foreach ($logger->getHandlers() as $handler) { // 给所有通道添加PID处理器 $handler->pushProcessor([$this, 'processLogRecord']); // 只给本地文件日志设置自定义格式 if ($handler instanceof StreamHandler) { $handler->setFormatter($this->getLogFormatter()); $handler->pushProcessor(function ($record) { return Arr::add($record, 'prefix', getmypid()); }); } } } public function processLogRecord(array $record): array { $record['extra'] += [ 'pid' => getmypid(), ]; return $record; } protected function getLogFormatter() { $format = "[%datetime%] %channel%.%level_name%: %prefix%.%message% %context% %extra%\n"; return new LineFormatter($format, null, true, true); } }
方案二:直接在CreateStackdriverLogger中添加处理器
如果你不想依赖Laravel的tap机制,也可以直接在创建Stackdriver Logger的过程中注入处理器,这样更直观:
修改CreateStackdriverLogger.php:
use Google\Cloud\Logging\LoggingClient; use Monolog\Handler\PsrHandler; use Monolog\Logger; use App\Logging\ProcessorTap; // 导入你的处理器类 class CreateStackdriverLogger { /** * Create a custom Monolog instance. * * @param array $config * @return \Monolog\Logger */ public function __invoke(array $config) { $logName = isset($config['logName']) ? $config['logName'] : 'app'; $psrLogger = LoggingClient::psrBatchLogger($logName); $handler = new PsrHandler($psrLogger); $logger = new Logger($logName, [$handler]); // 直接添加PID处理器到Stackdriver Logger $processor = new ProcessorTap(); $logger->pushProcessor([$processor, 'processLogRecord']); return $logger; } }
测试验证
修改完成后,记得清理配置缓存:
php artisan config:clear
然后触发一条日志(比如Log::debug('Test log with PID');),去Google Cloud Console的Logging页面查看这条日志的详情。你会在jsonPayload字段下找到extra.pid,里面就是当前进程的ID啦!
内容的提问来源于stack exchange,提问作者JimmyJige

