How to Add extra Data to Log Messages via a Processor
Monolog allows you to process every record before logging it by adding some extra data. This is the role of a processor, which can be applied for the whole handler stack or only for a specific handler or channel.
A processor is a callable receiving the record as its first argument.
Processors are configured using the monolog.processor DIC tag. See the
reference about it.
Adding a Session/Request Token
Sometimes it is hard to tell which entries in the log belong to which session and/or request. The following example will add a unique token for each request using a processor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
// src/Logger/SessionRequestProcessor.php
namespace App\Logger;
use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;
use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
use Symfony\Component\HttpFoundation\RequestStack;
class SessionRequestProcessor implements ProcessorInterface
{
    public function __construct(
        private RequestStack $requestStack
    ) {
    }
    // method is called for each log record; optimize it to not hurt performance
    public function __invoke(LogRecord $record): LogRecord
    {
        try {
            $session = $this->requestStack->getSession();
        } catch (SessionNotFoundException $e) {
            return $record;
        }
        if (!$session->isStarted()) {
            return $record;
        }
        $sessionId = substr($session->getId(), 0, 8) ?: '????????';
        $record->extra['token'] = $sessionId.'-'.substr(uniqid('', true), -8);
        return $record;
    }
}
    Next, register your class as a service, as well as a formatter that uses the extra information:
1 2 3 4 5 6 7 8 9 10
# config/services.yaml
services:
    monolog.formatter.session_request:
        class: Monolog\Formatter\LineFormatter
        arguments:
            - "[%%datetime%%] [%%extra.token%%] %%channel%%.%%level_name%%: %%message%% %%context%% %%extra%%\n"
    App\Logger\SessionRequestProcessor:
        tags:
            - { name: monolog.processor }
    Finally, set the formatter to be used on whatever handler you want:
1 2 3 4 5 6 7 8
# config/packages/prod/monolog.yaml
monolog:
    handlers:
        main:
            type: stream
            path: '%kernel.logs_dir%/%kernel.environment%.log'
            level: debug
            formatter: monolog.formatter.session_request
    If you use several handlers, you can also register a processor at the handler level or at the channel level instead of registering it globally (see the following sections).
When registering a new processor, instead of adding the tag manually in your
configuration files, you can use the #[AsMonologProcessor] attribute to
apply it on the processor class:
1 2 3 4 5 6 7 8 9 10
// src/Logger/SessionRequestProcessor.php
namespace App\Logger;
use Monolog\Attribute\AsMonologProcessor;
#[AsMonologProcessor]
class SessionRequestProcessor
{
    // ...
}
    The #[AsMonologProcessor] attribute takes these optional arguments:
channel: the logging channel the processor should be pushed to;handler: the handler the processor should be pushed to;method: the method that processes the records (useful when applying the attribute to the entire class instead of a single method).
3.8
The #[AsMonologProcessor] attribute was introduced in MonologBundle 3.8.
Symfony's MonologBridge provides processors that can be registered inside your application.
- DebugProcessor
 - Adds additional information useful for debugging like a timestamp or an error message to the record.
 - TokenProcessor
 - Adds information from the current user's token to the record namely username, roles and whether the user is authenticated.
 - SwitchUserTokenProcessor
 - Adds information about the user who is impersonating the logged in user, namely username, roles and whether the user is authenticated.
 - WebProcessor
 - Overrides data from the request using the data inside Symfony's request object.
 - RouteProcessor
 - Adds information about current route (controller, action, route parameters).
 - ConsoleCommandProcessor
 - Adds information about the current console command.
 
See also
Check out the built-in Monolog processors to learn more about how to create these processors.
Registering Processors per Handler
You can register a processor per handler using the handler option of
the monolog.processor tag:
1 2 3 4 5
# config/services.yaml
services:
    App\Logger\SessionRequestProcessor:
        tags:
            - { name: monolog.processor, handler: main }
    Registering Processors per Channel
By default, processors are applied to all channels. Add the channel option
to the monolog.processor tag to only apply a processor for the given channel:
1 2 3 4 5
# config/services.yaml
services:
    App\Logger\SessionRequestProcessor:
        tags:
            - { name: monolog.processor, channel: 'app' }