Adrian Lynch
Adrian Lynch

Reputation: 8494

Extend Laravel log prefix to include custom environment variable

For a Laravel 5.7 app I'd like to add an additional bit of info to the default log prefix.

A log entry currently looks like this:

[2020-05-13 13:07:42] production.INFO: Information here...

I'd like to extend the prefix to make it:

[2020-05-13 13:07:42] PREFIX.production.INFO: Information here...

With PREFIX coming from an environment variable, LOG_PREFIX:

LOG_CHANNEL=daily
LOG_PREFIX=PREFIX

I don't mind using a regex to change production.INFO to PREFIX.production.INFO in a custom formatter.

I have added a tap to the log channel:

'daily' => [
    'driver' => 'daily',
    'path' => storage_path('logs/laravel.log'),
    'level' => 'debug',
    'days' => 7,
    'tap' => [App\Logging\CustomizeFormatter::class],
]

It's in the CustomizeFormatter class's invoke method that I've come unstuck:

class CustomizeFormatter
{
    /**
     * Customize the given logger instance.
     *
     * @param  \Illuminate\Log\Logger  $logger
     * @return void
     */
    public function __invoke($logger)
    {
        // What to add here?
    }
}

What could be used in there to do what I need?

Is this the wrong path to be taking?

Thanks.

Using the answer found here https://stackoverflow.com/a/34289039/121946 I can add the prefix as extra info at the end of the message using:

public function __invoke($logger)
{
    foreach ($logger->getHandlers() as $handler) {
      $handler->pushProcessor(function ($record) {
          $record['extra']['prefix'] = env('LOG_PREFIX');
          return $record;
      });
  }
}

Looking at the $record, I don't see the full log text, only the custom part:

array:7 [▼
  "message" => "Information here..."
  "context" => []
  "level" => 200
  "level_name" => "INFO"
  "channel" => "production"
  "datetime" => DateTime @1589377784 {#953 ▶}
  "extra" => []
]

Upvotes: 2

Views: 2301

Answers (1)

Remul
Remul

Reputation: 8252

Adding it to the extras will not display it how you want, here is the default line format:

[%datetime%] %channel%.%level_name%: %message% %context% %extra%

As you can see the extras are at the end, so it would produce something like this:

[2020-05-13 16:50:20] development.INFO: [] {"prefix":"MyPrefix"}

This is what you could do instead:

<?php

namespace App\Logging;

use Illuminate\Log\Logger;
use Illuminate\Support\Arr;
use Monolog\Formatter\LineFormatter;

class CustomizeFormatter
{
    /**
     * Customize the given logger instance.
     *
     * @param  Logger  $logger
     *
     * @return void
     */
    public function __invoke($logger)
    {
        foreach ($logger->getHandlers() as $handler) {
            $handler->pushProcessor(function ($record) {
                return Arr::add($record, 'prefix', env('LOG_PREFIX'));
            });
            $handler->setFormatter(tap(new LineFormatter(
                "[%datetime%] %prefix%.%channel%.%level_name%: %message% %context% %extra%\n",
                'Y-m-d H:i:s',
                true,
                true
            ), function ($formatter) {
                $formatter->includeStacktraces();
            }));
        }
    }
}

This will produce the following:

[2020-05-13 16:52:24] MyPrefix.development.INFO: []  

What we do here is add a new processor and add the key prefix to it. We can then use this key on the line formatter and are able decide where we want to display it with %prefix%

Upvotes: 6

Related Questions