Monolog:将不同通道和多个处理程序记录到分组日志文件 + 专用日志文件

Posted

技术标签:

【中文标题】Monolog:将不同通道和多个处理程序记录到分组日志文件 + 专用日志文件【英文标题】:Monolog: log different channels and multiple handlers to grouped log file + dedicated log files 【发布时间】:2015-04-20 23:33:32 【问题描述】:

我在配置 Monolog 以处理“嵌套记录器”时遇到了一些问题。

我想做的事:

从服务记录到专用文件(每个服务一个)从所有服务到一个文件。每个记录器也应由monolog.handlers.console 处理。

我为什么要这样做

每个服务都有逻辑,但可以使用来自 DI 的其他服务。我想知道一个服务到底记录了什么,所以我想要每个服务的专用记录器(带有自定义通道和自定义日志文件)。 但是当服务依赖其他服务时,我想在一个文件中按时间顺序读取日志。

我有什么

app/config.yml:

monolog:
    handlers:
        my_handler:
            type:     stream
            path:     %kernel.logs_dir%/%kernel.environment%.my.log
            level:    info
            handler:  my_bundle_handler

src/My/Bundle/Resources/config/config.yml

services:
    # LOGGERS
    my_logger:
        class: Symfony\Bridge\Monolog\Logger
        arguments: [my_logger]
        calls:
            - [pushHandler, [@monolog.handler.console]]
            - [pushHandler, [@my_bundle_handler]]
        tags:
            -  name: monolog.logger, channel: my_channel

    # HANDLERS
    my_bundle_handler:
        abstract: true # Without it it will throw exception
        type: group
        members: [my_service_handler]
        channels: ["my_channel"]
        tags:
            -  name: log_handler 

    my_service_handler:
        class: Monolog\Handler\StreamHandler
        arguments: [%kernel.logs_dir%/%kernel.environment%.my_service.log, 100]
        channels: ["my_channel"]
        tags:
            -  name: log_handler 

它没有按预期工作。它记录到my_service.log,但不记录到my.log

有没有可能实现我想要的?

【问题讨论】:

问题解决了吗? 还没有,我没有足够的时间来试验它.. 它不会解决您的问题,但可能会为您节省一些时间并改善日志处理体验,请尝试loggly.com @FrancescoCasula 我做到了,请参阅下面接受的答案的评论。 @veNuker 实际上我们现在使用 ELK 堆栈并将一些日志(错误+)发送到 Logstash,使用 Monolog gelf 处理程序。 【参考方案1】:

独白中的频道完全按照您的意愿工作。示例独白配置

app/config.yml

monolog:
  channels: ['deletion']
  handlers:
    main:
        type:         fingers_crossed
        action_level: error
        handler:      grouped_main
        formatter: "monolog.formatter.request"
        buffer_size: 30
#        if you will set stop_buffering: true - you will get ALL events after first error. It could produce huge logs for console
        stop_buffering: false

#   this is for getsentry.com error catching
    sentry:
        type:  raven
        dsn:   '%sentry_url%'
        level: notice

    # Groups
    grouped_main:
        type:    group
        members: [sentry, streamed_main, streamed_main_brief]

    # Streams
    streamed_main:
        type:  stream
        path:  "%kernel.logs_dir%/%kernel.environment%.log"

    streamed_main_brief:
        type:  stream
        path:  "%kernel.logs_dir%/%kernel.environment%_brief.log"
        formatter: monolog.brief_formatter

    console:
        type: console
        formatter: monolog.console_formatter

    deletion:
         # log deletion related messages
        level:    debug
        type:     stream
        path:     '%kernel.logs_dir%/deletion.log'
        channels: ['deletion']
        formatter: monolog.brief_formatter

services:
    my_service:
        class: Monolog\Processor\IntrospectionProcessor
        tags:
            -  name: monolog.processor 
    monolog.console_formatter:
        class: Symfony\Bridge\Monolog\Formatter\ConsoleFormatter
        arguments:
            - "<fg=black;bg=green>[%%datetime%%]</fg=black;bg=green> %%start_tag%%%%message%%%%end_tag%%\n"
    monolog.brief_formatter:
        class: Monolog\Formatter\LineFormatter
        arguments:
            - "[%%datetime%%] %%message%%\n"
#            default format is
#            - "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"        

如果你要添加类似的代码

$this->getContainer()->get("logger")->info("Sample info");
$this->getContainer()->get("monolog.logger.deletion")->info("Deletion channel info");
$this->getContainer()->get("monolog.logger.deletion")->error("Deletion channel error");
$this->getContainer()->get("monolog.logger.deletion")->info("Deletion channel info #2");

您将获得 3 个具有此类内容的日志文件

频道日志文件

deletion.log
[2016-11-11 12:43:18] Deletion channel info
[2016-11-11 12:43:18] Deletion channel error
[2016-11-11 12:43:19] Deletion channel info #2

默认环境日志文件

dev.log
[2016-11-11 12:43:18] event.DEBUG: Notified event "console.command" to listener "Symfony\Component\HttpKernel\EventListener\DebugHandlersListener::configure". [] "file":"...."
[2016-11-11 12:43:18] event.DEBUG: Notified event "console.command" to listener "Symfony\Bridge\Monolog\Handler\ConsoleHandler::onCommand". [] "file":"...."
[2016-11-11 12:43:18] app.INFO: Sample info [] "file":"..."
[2016-11-11 12:43:18] deletion.INFO: Deletion channel info [] "file":"...."
[2016-11-11 12:43:18] deletion.ERROR: Deletion channel error [] "...."

简短的环境日志

[2016-11-11 12:43:18] Notified event "console.command" to listener "Symfony\Component\HttpKernel\EventListener\DebugHandlersListener::configure".
[2016-11-11 12:43:18] Notified event "console.command" to listener "Symfony\Bridge\Monolog\Handler\ConsoleHandler::onCommand".
[2016-11-11 12:43:18] Sample info
[2016-11-11 12:43:18] Deletion channel info
[2016-11-11 12:43:18] Deletion channel error

还要注意,因为stop_buffering: false 错误后的通知不会出现在dev.log,dev_brief.log,但会出现在delete.log

你应该试试哨兵——它的产品很棒,他的主人很酷:)

【讨论】:

是的,我认为最好使用 MonologBu​​ndle 的配置(定义了通道的处理程序),但前提是 DI 配置已经存在(现有的应用程序,以前的开发人员有一些自己的约定)我不想重构它那么多。但这似乎是唯一的方法。非常感谢您的示例,我会尝试(我们有关于记录器重构的未决问题)。 经过很长时间,我终于设法用 MonologBu​​ndle 的配置重构了我们的记录器,是的,一切都可以通过处理程序堆栈来实现。有时它并不直观,但是有很多开箱即用的处理程序、处理器和格式化程序,因此每个日志记录都可以放在您想要的位置。谢谢。 作为替代方案,您可以使用 Monolog-Cascade github.com/theorchard/monolog-cascade,它与框架无关并依赖于简单的 yaml、json 或 php 配置文件 Monolog-cascade 并不是那么最新,请参阅github.com/Seldaek/monolog/pull/1580。

以上是关于Monolog:将不同通道和多个处理程序记录到分组日志文件 + 专用日志文件的主要内容,如果未能解决你的问题,请参考以下文章

Monolog,如何将 PHP 数组记录到控制台?

Monolog - Logging for PHP

Symfony2 Monolog 配置为使用 raven 处理程序(Sentry)

Monolog:捕获错误/异常并在响应中输出消息的处理程序(根据 PHP 默认)

The PHP Package 之 monolog[转]

Monolog stdout/stderr 记录到 Docker 中的当前终端进程