it-swarm.com.de

Behandeln Sie die Datenbankverbindungsausnahme über einen benutzerdefinierten Handler

Ich möchte die Datenbankverbindungsausnahmen mit einem benutzerdefinierten Handler abfangen. Ich habe bereits einen Handler erstellt, der die Standard-Logger-Factory überschreibt, aber jetzt möchte ich diesen benutzerdefinierten Handler verwenden, um Datenbankausnahmen zu protokollieren, ohne den Kern zu hacken.

Ich kann sehen, dass der Verbindungstreiber den folgenden Code in open() verwendet.

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;
}

Ich bin nicht sicher, wie ich die Ausnahme abfangen und mit dem Handler protokollieren kann. Wie kann ich das erreichen?

4
arpitr

Um die Protokollierung für eine bestimmte Ausnahme zu handhaben, implementieren Sie einen Ausnahmeteilnehmer mit einer Priorität über 50, damit er vor Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber Ausgeführt wird:

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 }

Wenn Sie keine Antwort festlegen, protokolliert dieser Abonnent nur den Fehler und die Antwort wird von einem Abonnenten mit einer niedrigeren Priorität festgelegt. In diesem Fall erhalten Sie zwei Protokolleinträge, einen von Ihrem Abonnenten und einen von ExceptionLoggingSubscriber, da der Dispatcher die Ereignisabonnenten ausführt, bis einer eine Antwort zurückgibt. Die Protokollierung stoppt dies nicht.

Eine andere Option wäre, ExceptionLoggingSubscriber zu erweitern, den benutzerdefinierten Code in ExceptionLoggingSubscriber :: onException einzufügen und die übergeordnete Methode aufzurufen, um die Standardprotokollierung auszuführen, wenn Ihr benutzerdefinierter Code nicht angewendet wird. Anstatt den Dienst in mymodule.services.yml zu platzieren, müssen Sie den vorhandenen Dienst im Container austauschen, siehe https://www.drupal.org/docs/8/api/services-and-dependency- Injektion/Änderung bestehender Dienste, die dynamische Dienste bereitstellen

Weitere Informationen zur Ausnahmebehandlung finden Sie hier Wie werden Ausnahmen behandelt?

5
4k4