Symfony2:在登录不同文件时使用处理器

时间:2012-07-17 10:09:01

标签: logging symfony processor formatter

我想将我的应用程序日志写入另一个文件,而不是Symfony2编写自己的日志和系统日志。我明白我需要像这样创建自己的服务:

services:
    actionslogger:
        class: Symfony\Bridge\Monolog\Logger
        arguments: [app]
        calls:
             - [pushHandler, [@actionslogger_handler]]
    actionslogger_handler:
        class: Monolog\Handler\StreamHandler       
        arguments: [%kernel.logs_dir%/actions_%kernel.environment%.log, 200]

当我在我的应用程序中使用 $ logger = $ this-> get('actionslogger'); 时,这很好用,所以没关系。 但我也想使用Formatter和Processor来管理我的日志写入方式。为此,我使用此配置:

services:
    actionslogger.formatter.session_request:
        class: Monolog\Formatter\LineFormatter
        arguments:
            - "[%%datetime%%] [%%extra.token%%] %%channel%%.%%level_name%%: %%message%%\n"

    actionslogger.processor.session_request:
        class: My\Bundle\LogProcessor
        arguments:  [ @session ]
        tags:
            - { name: actionslogger.processor, method: processRecord }

我可以将此Formatter和Processor与Symfony2默认记录器配合使用此配置:

monolog:
    handlers:
        main:
            type:  stream
            path:  %kernel.logs_dir%/%kernel.environment%.log
            level: debug
            formatter: actionslogger.formatter.session_request

但如果我可以将Formatter与我自己的记录器一起使用,我就无法使用处理器。这是我的配置:

services:
    actionslogger.formatter.session_request:
        class: Monolog\Formatter\LineFormatter
        arguments:
            - "[%%datetime%%] [%%extra.token%%] %%channel%%.%%level_name%%: %%message%%\n"

    actionslogger.processor.session_request:
        class: My\Bundle\LogProcessor
        arguments:  [ @session ]
        tags:
            - { name: actionslogger.processor, channel: app, method: processRecord, handler: @actionslogger_handler }

    actionslogger:
        class: Symfony\Bridge\Monolog\Logger
        arguments: [app]
        calls:
             - [pushHandler, [@actionslogger_handler]]
    actionslogger_handler:
        class: Monolog\Handler\StreamHandler       
        arguments: [%kernel.logs_dir%/actions_%kernel.environment%.log, 200]
        calls:
             #- [pushProcessor, [???]]
             - [setFormatter, [@actionslogger.formatter.session_request]]

处理器配置中的标签通道和处理程序似乎没用。

如何使处理器与记录器配合使用? 我应该将什么传递给注释行中的pushProcessor方法(如果这可能是一个有效的选项)?

感谢您的帮助。

注意:使用Symfony 2.0.0

2 个答案:

答案 0 :(得分:1)

processRecord方法重命名为__invoke。 这使得LogProcessor实例可以调用,并且您可以将相应的serice作为处理器传递。

答案 1 :(得分:0)

回答自己:

好吧,我找不到如何设置这个,所以我最终得到了这个不那么重的解决方案:

我创建了一个新的记录器,这非常简单,并且在构造函数中影响我的全新处理器,因此文件在My / Bundle中,如下所示:

#LogProcessor.php

use Symfony\Component\HttpFoundation\Session;
class LogProcessor
{
    private $session;
    private $token;
    public function __construct(Session $session)
    {
        $this->session = $session;
    }
    public function processRecord(array $record)
    {
        if (null === $this->token) {
            try {
                $this->token = ($this->session->getId());
            } catch (\RuntimeException $e) {
                $this->token = '????????';
            }
            $this->token .= '#' . substr(uniqid(), -8);
        }
        $record['extra']['token'] = $this->token;
        $record['extra']['context'] = "";
        foreach($record['context'] as $key=>$value) {
            $key=str_replace(array("=","#","|"),"",$key);
            $value=str_replace(array("=","#","|"),"",$value);
            $record['extra']['context'].=$key."=".$value."#";
        }
        return $record;
    }
}

#MyLogger.php

use Symfony\Bridge\Monolog\Logger;
use Symfony\Component\HttpFoundation\Session;
use My\Bundle\LogProcessor;

class MyLogger extends Logger {
    private $session;
    private $processor;

    public function __construct($name, Session $session)
    {
        parent::__construct($name);
        $this->session= $session;
        $this->processor= new LogProcessor($session);
        $this->pushProcessor((array($this->processor, 'processRecord')));
    }   
}

(如果我想稍后修改Logger的addRecord方法,这甚至会派上用场)

然后我创建一个这样的新服务:

#app/config/config.yml or src/My/Bundle/Resources/config/services.yml (if imported in app/config/config.yml)

services:
    mylogger:
        class: My\Bundle\MyLogger
        arguments: [app, @session]
        calls:
             - [pushHandler, [@mylogger.handler]]
    mylogger.handler:
        class: Monolog\Handler\StreamHandler       
        arguments: [%kernel.logs_dir%/actions_%kernel.environment%.log, 200] # 200 means "INFO"
        calls:
             - [setFormatter, [@monolog.formatter.compactformat]]
    monolog.formatter.compactformat:
        class: Monolog\Formatter\LineFormatter
        arguments:
            - "%%datetime%%|%%channel%%|%%level_name%%|%%extra.token%%|%%message%%|%%extra.context%%\n"

我走了。我现在可以使用我的新日志服务,使用我的Formatter /和/我的处理器,并按照我们想要的方式使用它们(这里:以易于使用的格式添加会话ID和日志上下文信息)。

#MyController.php
public function myMethod() {
    ...
    $logger = $this->get('mylogger');
    $logger->info('ACCESS PAGE', array('user'=>$userName, 'IP'=>$userIP, 'section'=>$section));
    ...
}

无论如何,如果某人有我的第一个问题的答案(关于如何在个人日志记录服务上直接在配置中链接处理器),请在此处发布。