Log PHP fatal errors in Symfony2 using Monolog Log PHP fatal errors in Symfony2 using Monolog symfony symfony

Log PHP fatal errors in Symfony2 using Monolog


Thanks to @jenechka, who pointed me to the right direction, I think I found a solution:

services.yml:

    vir.exception.listener:    class: %vir.exception.listener.class%    arguments: ["@logger"]    tags:        - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

Error Handler:

<?phpnamespace Mitecube\VoglioilruoloBundle\Listener;use Symfony\Component\Debug\ErrorHandler;use Symfony\Component\HttpKernel\Event\GetResponseEvent;use Psr\Log\LoggerInterface;class VoglioilruoloErrorHandler extends ErrorHandler {    private $logger;    private $prevErrorHandler;    public function __construct(LoggerInterface $logger)    {        $this->logger = $logger;        $this->prevErrorHandler = set_error_handler(array($this, 'handle'));        register_shutdown_function(array($this, 'handleFatal'));    }    public function onKernelRequest(GetResponseEvent $event)    {    }    public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())    {        $this->logger->error($level . ": " . $message . " - in file " . $file . " - at line " . $line);        return parent::handle($level, $message, $file, $line, $context);    }} 

In this way I able to log each error to monolog. I don't think this solution can be considered a "best practice", so I'm still looking for a better solution.


Create exception listener as described here http://symfony.com/doc/current/cookbook/service_container/event_listener.html

And see here http://symfony.com/doc/current/reference/dic_tags.html#monolog-logger how to send logger as argument to your listener

Service example configuration:

# src/Acme/DemoBundle/Resources/config/services.ymlparameters:    # ...services:    # ...    kernel.listener.your_listener_name:        class: Acme\DemoBundle\EventListener\AcmeExceptionListener        arguments: ["@logger"]        tags:            - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }            - { name: monolog.logger, channel: tema }

Listener example:

// src/Acme/DemoBundle/EventListener/AcmeExceptionListener.phpnamespace Acme\DemoBundle\EventListener;use Symfony\Component\Debug\ExceptionHandler;use Symfony\Component\HttpKernel\Event\GetResponseEvent;use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;use Symfony\Component\HttpFoundation\Response;use Psr\Log\LoggerInterface;class ExceptionListener extends ExceptionHandler{    private $logger;    private $prevExceptionHandler;    public function __construct(LoggerInterface $logger)    {        $this->logger = $logger;        // Set our handle method as fatal exception handler.        // It is required to extend Symfony\Component\Debug\ExceptionHandler        $this->prevExceptionHandler = set_exception_handler(array($this, 'handle'));    }    public function onKernelRequest(GetResponseEvent $event)    {    }    /**     * Handles non fatal exceptions (normal way).     */    public function onKernelException(GetResponseForExceptionEvent $event)    {        // You get the exception object from the received event        $exception = $event->getException();        // Log exception.        $this->logger->error($exception->getMessage());        // ...    }    /**     * Overwrite ExceptionHandler method.     */    public function handle(\Exception $exception) {        // Call our custom handler.        $this->onFatalErrorException($exception);        // Call exception handler that was overridden.        // Or try to call parent::handle($exception)        if (is_array($this->prevExceptionHandler) && $this->prevExceptionHandler[0] instanceof ExceptionHandler) {            $this->prevExceptionHandler[0]->handle($exception);        }    }    public function onFatalErrorException(\Exception $exception)    {        // Do anything you want...        $this->logger->error('Hey, I got it: '. $exception->getMessage());    }}

UPDATED: I have improved exception listener and now it handles fatal exceptions. Tested (on dev environment)!