Add extra information to the Symfony error logs

Published on 2019-03-19 • Modified on 2019-03-19

When a bug occurs, sometimes it's hard to know from where it comes from. Having more context can help and allows to find and to reproduce issues more easily. In the following example we will add some information coming from the application: the server, the environment and the version. And, if a Request object is available we add the current URI and the referrer if they are set. The EnvProcessor service must be tagged with monolog.processor and declared in the services.yaml file. Eventually you have to bind the parameters so they can be identified. (only the $appEnv (APP_ENV) parameter is common to all Symfony4/Flex applications)


<?php

declare(strict_types=1);

namespace App\Log\Processor;

use Monolog\LogRecord;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

use function Symfony\Component\String\u;

/**
 * Add extra data to logs.
 *
 * @see http://symfony.com/doc/current/logging/processors.html
 */
final class EnvProcessor
{
    /**
     * Check out the doc to see you to bind your parameters. In this case:
     * - "app_env" and "app_server" come from the ".env" file and are made available in services.yaml:
     * - app_env: '%env(APP_ENV)%'
     * - "app_version" comes from "services.yaml"
     * - "$requestStack" is the standard Symfony value object.
     *
     * @see https://symfony.com/doc/current/service_container.html#binding-arguments-by-name-or-type
     */
    public function __construct(
        private readonly string $appEnv,
        private readonly string $appServer,
        private readonly string $appVersion,
        private readonly RequestStack $requestStack)
    {
    }

    /**
     * Add environment extra data to the log record to ease debug.
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        /** @var array<string> $extra */
        $extra = $record['extra'] ?? [];
        $extra['app_server'] = $this->appServer;
        $extra['app_env'] = $this->appEnv;
        $extra['app_version'] = $this->appVersion;

        $request = $this->requestStack->getCurrentRequest();
        if ($request instanceof Request) {
            $uri = u($request->getUri())->trim();
            if (!$uri->isEmpty()) {
                $extra['uri'] = $uri->toString();
            }

            // prevents hacking attempts
            try {
                $referer = u($request->headers->get('referer'))->trim();
            } catch (\Exception) {
                $referer = u('Referer is an invalid UTF8 string.');
            }

            if (!$referer->isEmpty()) {
                $extra['referer'] = $referer->toString();
            }

            $ip = u($request->getClientIp())->trim();
            if (!$ip->isEmpty()) {
                $extra['ip'] = $ip->toString();
                try {
                    $extra['host'] = gethostbyaddr($extra['ip']);
                } catch (\Exception) {
                    $extra['host'] = 'Exception when resolving host';
                }
            }
        }

        $record['extra'] = $extra;

        return $record;
    }
}

 More on Stackoverflow   Read the doc  Random snippet

  Work with me!