7

I want to catch the database connection exceptions with a custom handler. I have already built an handler which is overriding the default logger factory, but now I want to use that custom handler to log database exceptions, without hacking the core.

I can see the connection driver uses the following code in open().

try {
  $pdo = new \PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
}
catch (\PDOException $e) {
  if ($e->getCode() == static::DATABASE_NOT_FOUND) {
    throw new DatabaseNotFoundException($e->getMessage(), $e->getCode(), $e);
  }
  if ($e->getCode() == static::ACCESS_DENIED) {
    throw new DatabaseAccessDeniedException($e->getMessage(), $e->getCode(), $e);
  }
  throw $e;
}

I am not sure how I can catch the exception and log it using the handler. How can I achieve this?

0

1 Answer 1

8

To handle the logging for a specific exception implement an exception subscriber with a priority higher than 50, so that it runs before Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber:

src/EventSubscriber/ExampleExceptionSubscriber

namespace Drupal\mymodule\EventSubscriber;

use Drupal\Core\Database\DatabaseAccessDeniedException;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Example for catching a DatabaseAccessDeniedException
 */
class ExampleExceptionSubscriber implements EventSubscriberInterface {

  /**
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $logger;

  public function __construct(LoggerChannelFactoryInterface $logger) {
    $this->logger = $logger;
  }

  public function onException(GetResponseForExceptionEvent $event) {
    $exception = $event->getException();
    if ($exception instanceof DatabaseAccessDeniedException) {
      $this->logger->get('php')->error('Custom logging message');
      $response = new Response('Custom error message', 500);
      $event->setResponse($response);
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::EXCEPTION][] = ['onException', 60];
    return $events;
  }
}

mymodule.services.yml

services:
  mymodule.exception.subscriber:
    class: Drupal\mymodule\EventSubscriber\ExampleExceptionSubscriber
    arguments: ['@logger.factory']
    tags:
      - { name: event_subscriber }

If you don't set a response this subscriber only logs the error and the response is set by a subscriber with a lower priority. In this case you get two log entries, one from your subscriber and one from ExceptionLoggingSubscriber, because the dispatcher runs the event subscribers until one returns a response. Logging does not stop this.

Another option would be to extend ExceptionLoggingSubscriber, put the custom code in ExceptionLoggingSubscriber::onException and call the parent method to run standard logging when your custom code doesn't apply. Instead of putting the service in mymodule.services.yml you need to swap the existing service in the container then, see https://www.drupal.org/docs/8/api/services-and-dependency-injection/altering-existing-services-providing-dynamic-services

You find more infos about exception handling here How do handle exceptions?

5
  • thanks @4k4, that looks promising, however I tried but it seems my subscriber is not getting called, I will debug. Thanks again, a big big help :)
    – arpitr
    Commented May 11, 2017 at 2:40
  • hi @arpitr . Did you manage to get a solution for this? My subscriber is not being called as well Commented Nov 14, 2019 at 9:08
  • Thank you for this. I eventually got it to work by putting qoutes around the class in the servives.yml file. '\Drupal\magri_rest\EventSubscriber\ExceptionsSubscriber' Commented Nov 14, 2019 at 12:04
  • @tendaitakas, this is strange that you needed to do this, I can't find any *.services.yml file with class names in quotes.
    – 4uk4
    Commented Nov 14, 2019 at 13:19
  • I corrected it when I saw this article. Commented Nov 14, 2019 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.