Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add additional information (Host, URL, etc.) to Symfony/Monolog log output?

I am working on my first Symfony based WebApp project. I have configured Symfony to not only write log messages to the different log files but also to send critical error messages immediately as e-mail. This works fine. However I would like to add some additional information to the default log messages to make it easier to find the actual error source.

Example: The Twig file of one pages loads the localized text from a .yml file. The texts contains an %about_link%placeholder that should be replaced by the route/URL to the About page. I forgot to this replacement, so the link did not point to an URL but to %about_link% instead. This leads to an NotFoundHttpException since no rout to %about_link% can be found...

No big deal. But to find the actual page/controller that contains this error was a bit tricky. The default log message shows the following:

[2015-12-14 17:19:36] request.ERROR: Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\NotFoundHttpException: "No route found for "GET /%25about_link%25"" at /long/path/to/symfony/.../RouterListener.php line 176 []

So the exception was thrown in RouterListener.php when trying to find a route to %about_link%. Fine, this does not give me any hint on which page this bad link is located.

Of course the call to the bad route does not have to be located on any page at all. The user could have entered the bad link directly. Symfony would have to store/remember the last page to give any hint about the possible source. So, is it possible to include this information at all?

Additionally I would like to add information about the Host the problem was reported on. I am running two instances of the WebApp: www.my_web_app.xy and betatest.my_web_app.xy and it would be a great help, if the log message would show if it comes from www or from betatest.

Adding this information to log messages I create on myself is no problem, but how can I add this information to messages generated by Symfony or third party code? I would have to intercept the log message somehow before it reaches the log handler. Is this possible?

like image 488
Andrei Herford Avatar asked Dec 15 '15 08:12

Andrei Herford


People also ask

What are the different levels of logs we can have in monolog?

Monolog log levels Monolog has the following log levels: DEBUG - detailed debug information. INFO - interesting events. NOTICE - normal but significant events.

Where is Symfony logs?

By default, log entries are written to the var/log/dev. log file when you're in the dev environment.

How to use Monolog in PHP?

php use Monolog\Level; use Monolog\Logger; use Monolog\Handler\StreamHandler; use Monolog\Handler\FirePHPHandler; // Create the logger $logger = new Logger('my_logger'); // Now add some handlers $logger->pushHandler(new StreamHandler(__DIR__. '/my_app.

What is monolog Symfony?

Monolog is the existing standard logging library for PHP. It is most popular in PHP frameworks such as Laravel and Symfony, where it implements a common interface for logging libraries. This article talks about the step-by-step process of using PHP Monolog in your application.


2 Answers

If you want to add extra information to log entries, you can do this with a processor. With a processor you can modify the record array, before it's parsed by a formatter. The extra part is shown at the end of the log entry.

<?php

namespace AppBundle\Monolog;

use Symfony\Component\HttpFoundation\RequestStack;

class WebProcessor
{
    private $requestStack;

    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }

    public function processRecord(array $record)
    {
        $request = $this->requestStack->getCurrentRequest();

        if ($request) {
            $record['extra']['host'] = $request->getHost();
            $record['extra']['url'] = $request->getRequestUri();
            // ...
        }

        return $record;
    }
}

Now add it to your services.yml to register it for all log entries:

app.monolog.processor.web:
    class: AppBundle\Monolog\WebProcessor
    arguments: ["@request_stack"]
    tags:
        - { name: monolog.processor, method: processRecord }
like image 58
Emii Khaos Avatar answered Sep 23 '22 01:09

Emii Khaos


Don't reinvent the wheel! There is no need to write your own WebProcessor, since Monolog already has it.

The only thing you have to do is add it to your services and tag it with monolog.processor:

# app/config/services.yml
services:
    Monolog\Processor\WebProcessor:
        tags: ['monolog.processor']

Monolog has even more built-in processors you can use. I decided to add multiple processors in my application:

# app/config/services/monolog.yml (I included services/*.yml in config.yml)
services:
    _defaults:
        tags: ['monolog.processor']
    Monolog\Processor\WebProcessor: ~
    Monolog\Processor\GitProcessor: ~
    Monolog\Processor\MemoryUsageProcessor: ~
    Monolog\Processor\MemoryPeakUsageProcessor: ~
    Monolog\Processor\IntrospectionProcessor: ~
like image 38
Stephan Vierkant Avatar answered Sep 22 '22 01:09

Stephan Vierkant