Monolog - 仅记录特定级别的错误

Monolog - logging only specific level of errors

我在 vanilla PHP 应用程序中使用 Monolog。

我只想记录特定级别的错误 - INFO 和不高于,因为我有其他处理程序。

这是我的代码:

<?php
$logger = new Logger('mylogger');
$logger->pushHandler(new StreamHandler(__DIR__.'/log/errors.log', Logger::WARNING));
$logger->pushHandler(new StreamHandler(__DIR__.'/log/info.log', Logger::INFO));

有什么方法可以仅将 INFO 消息记录到 info.log

bubble 参数设置为 false

$logger->pushHandler(new StreamHandler(__DIR__.'/log/info.log', Logger::INFO, false));

我今天遇到了同样的问题,这让我来到了这里。无论如何,我通过使用 Monologs FilterHandler 解决了它。

FilterHandler 允许您将另一个处理程序作为参数传递,然后指定将触发该处理程序的最小和最大日志记录级别。

有一个 few other handlers 在特定情况下很有用。

// Create the logging instance
$logger = new \Monolog\Logger('myLogger');

// Create error stream handler for error events and higher
$errorStreamHandler = new \Monolog\Handler\StreamHandler(
    'Some/DirectoryPath/error.log',
    \Monolog\Logger::ERROR);

// Create info stream handler for info events and higher
$infoStreamHandler = new \Monolog\Handler\StreamHandler(
    'Some/DirectoryPath/Info.log',
    \Monolog\Logger::INFO);

// Create filter handler to make sure info stream only logs info events
// Pass in the info handler 
// Debug is the minimum level this handler will handle
// Info is the maximum level this handler will handle
$infoFilterHandler = new \Monolog\Handler\FilterHandler(
    $infoStreamHandler,
    \Monolog\Logger::DEBUG,
    \Monolog\Logger::INFO);

// Add the handlers to logger
$logger->pushHandler($errorStreamHandler);
$logger->pushHandler($infoFilterHandler);

// Yay no errors in Info.log
$logger->addError("Some Error");
$logger->addInfo("Some Info");

更新阿里 参考\Monolog\Logger的source code查找可用的常量,然后将常量分配给变量。

$someVar = \Monolog\Logger::INFO;

$infoStreamHandler = new \Monolog\Handler\StreamHandler(
    'Some/DirectoryPath/Info.log',
    $someVar);

基于@Sasha Vas 的回答。

Monologs StreamHandler 有一个 bubble 参数,它可以完全按照你的要求做,避免日志冒泡到其他级别。

在 Laravel 5.6 之后,此未记录的功能也可用。

这是我的 channels 之一的样子:

'warning' => [
            'driver' => 'single',
            'level' => 'warning',
            'bubble' => false,
            'path' => storage_path('logs/warning.log'),
],

现在,如果我使用 Log::warning('warning') 它只会显示在 warning.log

选项 1:使用 bubble 参数

假设您的系统只生成 INFOERROR 级别的消息(或者更准确地说,生成的每个日志级别都有处理程序),完成将消息发送到正确处理程序的最简单方法是以正确的顺序设置处理程序堆栈并在处理程序的构造函数中使用 bubble 参数:

$logger = new \Monolog\Logger('ChannelName');

// Note that higher-level messages are higher in the stack (added last)
$logger->pushHandler(new \Monolog\Handler\StreamHandler(
    LOG_DIR.'info.log',
    \Monolog\Logger::INFO
));
$logger->pushHandler(new \Monolog\Handler\StreamHandler(
    LOG_DIR.'error.log',
    \Monolog\Logger::ERROR,
    false // Prevents messages from bubbling 'up' the handler stack
));

$logger->info('Test info message.'); // Only sent to info.log
$logger->error('Test error message.'); // Only sent to error.log

请记住,堆栈的处理方式为 'Last In First Out',因此最后添加到堆栈的项目是第一个处理的项目。由于日志级别是处理程序将处理的最低级别,因此处理程序应按从低到高的顺序添加到堆栈中。

bubble 参数,默认情况下为 true,指示消息是否应传播到堆栈中的其余处理程序(NOT 另一个答案中描述的日志级别)。通过在上面的代码中将其设置为 false,在错误处理程序处理消息后,不会调用堆栈的其余部分。

选项 2:使用 FilterHandler 包装器

如果您有针对系统生成的每个日志级别的处理程序,上述工作就很好。但如果不是这样呢?例如,如果您希望错误日志捕获级别 ERROR 及更高级别的任何内容,但您还想要一个只处理级别 ALERT 的处理程序,例如发送电子邮件通知,该怎么办?

Monolog 的 FilterHandler 是一个包装器,可让您指定处理程序将接收的日志级别。您可以指定从最小值到最大值的级别范围,或明确级别列表。

其构造函数采用以下参数:

Parameter Type Description Default
$handler callable HandlerInterface Handler or factory callable($record|null, $filterHandler)
$minLevelOrList int|array A list of levels to accept or a minimum level if maxLevel is provided Logger::DEBUG
$maxLevel int|string Maximum level to accept, only used if $minLevelOrList is not an array Logger::EMERGENCY
$bubble bool Whether the messages that are handled can bubble up the stack or not true

要使用它,我们只需将它添加到处理程序堆栈的顶部:

$logger = new \Monolog\Logger('ChannelName');

// Note that higher-level messages are higher in the stack (added last)
$logger->pushHandler(new \Monolog\Handler\StreamHandler(
    LOG_DIR.'info.log',
    \Monolog\Logger::INFO
));
$logger->pushHandler(new \Monolog\Handler\StreamHandler(
    LOG_DIR.'error.log',
    \Monolog\Logger::ERROR,
    false // Prevents messages from bubbling up the handler stack
));
// Use FilterHandler to only pass certain messages to a handler
$logger->pushHandler(new \Monolog\Handler\FilterHandler(
    new \Monolog\Handler\StreamHandler(LOG_DIR.'alerts.log'), // Handler to receive filtered messages
    [\Monolog\Logger::ALERT] // Explicit list only contains ALERT
));


$logger->info('Test info message.'); // Sent to info.log only
$logger->error('Test error message.'); // Sent to error.log
$logger->alert('Test alert message.'); // Sent to alerts.log and error.log
$logger->emergency('Test emergency message.'); // Sent to error.log

注意以下几点:

  • 未设置目标处理程序的日志级别,将其保留为默认值 Logger::DEBUG,因为 FilterHandler 将控制它接收的消息级别。
  • 默认保留冒泡 true,以便调用堆栈的其余部分。
  • Logger::ALERT 作为数组传递,因此它会被视为显式项目而不是最低级别,这样 EMERGENCY 消息就不会发送到 alerts.log

最后一件事:Monolog 附带 many other handlers 用于进行电子邮件等专业处理。为了简单起见,我只是使用 StreamHandler 作为目标处理程序。