Search code examples
phplogginglaravel-5.6formatter

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


In my laravel application there's need to format a message I need to send into slack. Hence I set a slack log channel into config/logging.php:

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

Also as seen on documentation I can do a monolog formater, hence I did the following:

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(...);
        }
    }
}

And specified it as tap into my log:

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

But in my formater where do I process the log entry itself? I mean:

  1. The $handler->setFormatter does not seem to be a method of \Illuminate\Log\Logger class.

  2. I cannot find out what method I need to override when I need to provide a custom format. I mean I have the invoke method then afterwards what?


Solution

  • The formatter for slack should be the following:

    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);
                }
            }
        }
    }
    

    And config the slack not to send attachment nessesary for the formatter to work:

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

    The setFormatter method takes a new Monolog Formatter as seen in: https://github.com/Seldaek/monolog/blob/master/doc/02-handlers-formatters-processors.md#formatters

    Also the pushProcessor allows you to populate extra fields on your message eg. Showing an emoji on your log message:

        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);
                }
            }
        }