2

在记录业务日志时,我们经常需要为每一条日志都补充上类似 RequestId 类的唯一标识串,方便后期快速的将某请求的相关的日志流 聚合 查询出来。首先,RequestId 是要单例贯穿整个请求生命周期的,如果在整个请求处理过程中,包括不同的服务层、模块,我都需要将 RequestId 透传或作为参数显示的传入 logger中,那代码简直不要太美观。

Monolog 作为最为流行的 PHP 日志组件,如果可以实现为每一条日志自动填充 RequestId,那使用起来是非常舒服的。

MonologpushProcessor 方法可以方便我们实现这一需求,pushProcessor 中的 processor 会对你记录的每一条日志进行处理并返回。

在请求的初始阶段,为本次请求生成一个全局的 RequestId,我是放在 Request 对象上,不同框架获取请求会话的 Request 单例对象的方法可能不同,大家理解就好。或者你可以单独使用一个单例对象去维护 RequestId,只要保证对当前请求是单例模式(放在 DI Container 中最好)。

<?php

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

class Log
$logger = new Logger('default');

// 添加处理器
$rfHandler = new RotatingFileHandler(__DIR__ . '/app_default.log', Logger::DEBUG);

$format = "[%datetime%] %channel%.%level_name%: %extra% %message% %context%\n";
$dateFormat = 'Y-m-d H:i:s';
$lFormatter = new LineFormatter($format, $dateFormat, true);

$rfHandler->setFormatter($lFormatter)
$logger->pushHandler($rfHandler);

// 就是在这里做处理啦 $request->getRequestId 自己去实现
$logger->pushProcessor(function ($log) {
    /** @var Request $request */
    $request = \request();//webman的
    $log['extra']['request-id'] = $request->getRequestId();
    return $log;
});
<?php
// 现在你就可以用日志服务了
$logger->info('this is monolog example');
$logger->info('this is log will auto fill requestId');

记得把 RequestId 返回给前端,这样问题反馈就容易追踪请求链路了。


big_cat
1.7k 声望130 粉丝

规范至上