Laravel 点击 Formatter:我实际上在哪里格式化消息?

Laravel Tap Formatter: where do I actually format the message?

在我的 laravel 应用程序中,需要格式化我需要发送到 slack 的消息。因此,我将一个松弛的日志通道设置为 config/logging.php:

'slack'         => [
    'driver'   => 'slack',
    'url'      => /*Censored Hook URL*/,
    'username' => 'MyApp',
    'emoji'    => ':gear:',
    'level'    => 'debug',
],

也如在 documentation 上看到的那样,我可以做一个独白格式化程序,因此我做了以下事情:

namespace App\Logging;

class SlackLogFormatter
{
    /**
     * Customize the given logger instance.
     *
     * @param  \Illuminate\Log\Logger  $logger
     * @return void
     */
    public function __invoke($logger)
    {
        foreach ($logger->getHandlers() as $handler) {
            $handler->setFormatter(...);
        }
    }
}

并将其指定为进入我的日志:

'slack'         => [
    'driver'   => 'slack',
    'tap' => [App\Logging\SlackLogFormatter::class]
    'url'      => /*Censored Hook URL*/,
    'username' => 'MyApp',
    'emoji'    => ':gear:',
    'level'    => 'debug',
],

但是在我的格式化程序中,我在哪里处理日志条目本身?我的意思是:

  1. $handler->setFormatter好像不是\Illuminate\Log\Logger的方法 class.

  2. 当我需要提供自定义格式时,我找不到需要重写的方法。我的意思是我有 invoke 方法,然后呢?

slack 的格式化程序应如下所示:

namespace App\Logging;

use Monolog\Formatter\LineFormatter;

class SlackLogFormatter
{
    /**
     * Customize the given logger instance.
     *
     * @param  \Illuminate\Log\Logger  $logger
     * @return void
     */
    public function __invoke($logger)
    {
        foreach ($logger->getHandlers() as $handler) {
            if ($handler instanceof SlackWebhookHandler) {
                $format=""; // Look on the Monolog's Line formatter documentation
                $formatter= new LineFormatter($format,"Y-m-d H:i:s");


                $handler->pushProcessor(function ($record) {
                   //Append extra info of formatting here
                });

                $handler->setFormatter($formatter);
            }
        }
    }
}

并配置 slack 不发送格式化程序工作所必需的附件:

'slack'         => [
    'driver'   => 'slack',
    'tap' => [App\Logging\SlackLogFormatter::class]
    'url'      => /*Censored Hook URL*/,
    'username' => 'MyApp',
    'emoji'    => ':gear:',
    'level'    => 'debug',
    'attachment' => FALSE,
],

setFormatter 方法采用了一个新的 Monolog 格式化程序,如下所示:https://github.com/Seldaek/monolog/blob/master/doc/02-handlers-formatters-processors.md#formatters

此外,pushProcessor 允许您在消息中填充额外的字段,例如。在您的日志消息中显示表情符号:

    public function __invoke($logger)
    {
        foreach ($logger->getHandlers() as $handler) {
            if ($handler instanceof SlackWebhookHandler) {
                $format="%emoji% %message%"; 
                $formatter= new LineFormatter($format,"Y-m-d H:i:s");

                $handler->pushProcessor(function ($record) {
                         $record['emoji']=":poop:";
                });

                $handler->setFormatter($formatter);
            }
        }
    }

Dimitrios 几乎是正确的(或者这可能适用于旧版本)但正如 Xavier 所说,如果您完全复制该代码,您将得到错误

Return value of Monolog\Handler\AbstractProcessingHandler::processRecord() must be of the type array, null returned

你会想要做这样的事情:

<?php

namespace App\Logging;

use Monolog\Formatter\LineFormatter;
use Monolog\Handler\SlackWebhookHandler;
use Request;

class CustomiseFormatter
{
    protected $request;

    public function __construct(Request $request = null)
    {
        $this->request = $request;
    }

    public function __invoke($logger)
    {
        foreach ($logger->getHandlers() as $handler) {
            if ($handler instanceof SlackWebhookHandler) {
                $handler->setFormatter(new LineFormatter(
                    '[%datetime%] %channel%.%level_name%: %message% %context% %extra%'
                ));

                $handler->pushProcessor([$this, 'processLogRecord']);
            }
        }
    }

    public function processLogRecord(array $record): array
    {
        $record['extra'] += [
            'url' => env("APP_URL"),
        ];

        return $record;
    }
}

同样,对于 extra 的修改方式,您可以更改任何其他值。