跳到内容

如何通过处理器向日志消息添加额外数据

编辑此页

Monolog 允许你在记录每个日志条目之前通过添加额外数据来处理它。这是处理器的作用,它可以应用于整个处理器堆栈,或者仅应用于特定的处理器或频道。

处理器是一个可调用对象,它接收记录作为它的第一个参数。处理器使用 monolog.processor DIC 标签配置。请参阅关于它的参考文档

添加 Session/请求令牌

有时很难分辨日志中的哪些条目属于哪个会话和/或请求。以下示例将使用处理器为每个请求添加一个唯一的令牌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// src/Logger/SessionRequestProcessor.php
namespace App\Logger;

use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;
use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
use Symfony\Component\HttpFoundation\RequestStack;

class SessionRequestProcessor implements ProcessorInterface
{
    public function __construct(
        private RequestStack $requestStack
    ) {
    }

    // method is called for each log record; optimize it to not hurt performance
    public function __invoke(LogRecord $record): LogRecord
    {
        try {
            $session = $this->requestStack->getSession();
        } catch (SessionNotFoundException $e) {
            return $record;
        }
        if (!$session->isStarted()) {
            return $record;
        }

        $sessionId = substr($session->getId(), 0, 8) ?: '????????';

        $record->extra['token'] = $sessionId.'-'.substr(uniqid('', true), -8);

        return $record;
    }
}

接下来,将你的类注册为服务,以及一个使用额外信息的格式化器

1
2
3
4
5
6
7
8
9
10
# config/services.yaml
services:
    monolog.formatter.session_request:
        class: Monolog\Formatter\LineFormatter
        arguments:
            - "[%%datetime%%] [%%extra.token%%] %%channel%%.%%level_name%%: %%message%% %%context%% %%extra%%\n"

    App\Logger\SessionRequestProcessor:
        tags:
            - { name: monolog.processor }

最后,设置要在你想要的任何处理器上使用的格式化器

1
2
3
4
5
6
7
8
# config/packages/prod/monolog.yaml
monolog:
    handlers:
        main:
            type: stream
            path: '%kernel.logs_dir%/%kernel.environment%.log'
            level: debug
            formatter: monolog.formatter.session_request

如果你使用多个处理器,你也可以在处理器级别或频道级别注册处理器,而不是全局注册(请参阅以下章节)。

当注册一个新的处理器时,你可以使用 #[AsMonologProcessor] 属性应用于处理器类,而不是在你的配置文件中手动添加标签

1
2
3
4
5
6
7
8
9
10
// src/Logger/SessionRequestProcessor.php
namespace App\Logger;

use Monolog\Attribute\AsMonologProcessor;

#[AsMonologProcessor]
class SessionRequestProcessor
{
    // ...
}

#[AsMonologProcessor] 属性接受这些可选参数

  • channel: 处理器应推送到的日志频道;
  • handler: 处理器应推送到的处理器;
  • method: 处理记录的方法(当将属性应用于整个类而不是单个方法时很有用)。

3.8

#[AsMonologProcessor] 属性在 MonologBundle 3.8 中引入。

Symfony 的 MonologBridge 提供了可以在你的应用程序内部注册的处理器。

DebugProcessor
向记录添加有用的调试信息,例如时间戳或错误消息。
TokenProcessor
向记录添加当前用户令牌的信息,包括用户名、角色以及用户是否已认证。
SwitchUserTokenProcessor
向记录添加关于正在模拟已登录用户的用户的信息,包括用户名、角色以及用户是否已认证。
WebProcessor
使用 Symfony 请求对象内部的数据覆盖来自请求的数据。
RouteProcessor
添加关于当前路由的信息(控制器、动作、路由参数)。
ConsoleCommandProcessor
添加关于当前控制台命令的信息。

另请参阅

查看内置的 Monolog 处理器,以了解更多关于如何创建这些处理器的信息。

为每个处理器注册处理器

你可以使用 monolog.processor 标签的 handler 选项为每个处理器注册一个处理器

1
2
3
4
5
# config/services.yaml
services:
    App\Logger\SessionRequestProcessor:
        tags:
            - { name: monolog.processor, handler: main }

为每个频道注册处理器

默认情况下,处理器应用于所有频道。将 channel 选项添加到 monolog.processor 标签以仅将处理器应用于给定的频道

1
2
3
4
5
# config/services.yaml
services:
    App\Logger\SessionRequestProcessor:
        tags:
            - { name: monolog.processor, channel: 'app' }
本作品,包括代码示例,在 Creative Commons BY-SA 3.0 许可下获得许可。
目录
    版本