ведение журнала — Лучшая практика регистрации пользовательских исключений в переполнении стека

У меня есть пользовательское исключение (которое может быть расширено в других пользовательских исключениях). Мой проект требует журнала всех пользовательских исключений (и всех его потомков), что происходит. У меня есть регистратор, который может регистрировать customException (и все остальное). Один из способов сделать это — явно регистрировать исключение, когда оно обрабатывается следующим образом.

try{
//some exception occur
}
catch(customeException $e)
{
$log->logException($e);
$e->showMessage(); // or do anything that we have to do with the error.
}

Так как мы регистрируем все customExceptions, я могу думать иначе, обновляя конструктор customException и регистрируя исключение прямо внутри конструктора. Таким образом, он гарантирует, что все customException регистрируются. Однако, если мы пойдем по этому пути, мои вопросы:

  1. Как внедрить регистратор в customException?
  2. Будет ли это против принципа SRP?
  3. Будет ли это считаться плохой практикой в ​​смысле ООП или какова лучшая практика в этом отношении?

4

Решение

Я думаю, что вставлять регистратор в CustomException не правильно, потому что (как вы указали) он нарушает SRP и увеличивает сложность ваших классов исключений.

Я предлагаю вам отделить Exception от ExceptionHandler. Класс исключения должен содержать только информацию о том, «что (и где) пошло не так». ExceptionHandler отвечает за регистрацию исключений (и выполнение какой-либо другой работы с исключением при необходимости).

Таким образом, вы можете настроить один глобальный ExceptionHandler (с помощью set_exception_handler а также set_error_handler или некоторый основанный на фреймворке механизм обработки исключений, такой как ExceptionListener Symfony), который поймает все необработанные исключения.

<?php

class ExceptionHandler {
/**
* @var Logger
*/
private $logger;

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

public function handle(Throwable $e)
{
$this->logger->logException($e);
}
}

В коде приложения вы все еще можете генерировать и ловить исключения. Я думаю, что есть 4 общие ситуации.

Полностью восстанавливаемые исключения

Это общий способ обработки восстанавливаемых исключений — таких ситуаций, когда вы вообще не хотите отказывать, но вам нужно что-то делать, когда такое исключение происходит.

<?php

try {
$methodThatThrowsException();
}
catch (DoesNotMatterException $e) {
// do some stuff and continue the execution
// note, that this exception won't be logged
}

Восстанавливаемое зарегистрированное исключение

То же, что и предыдущий, но вы хотите записать это исключение.

<?php

try {
$methodThatThrowsException();
}
catch (NonCriticalExceptionThatShouldBeLogged $e) {
$this->exceptionHandler->handle($e); // log exception
// do some stuff and continue the execution
}

Невосстановимые исключения с «финализатором»

Вы хотите выполнить определенную бизнес-логику, а затем потерпеть неудачу. Вы можете поймать исключение, обработать его и затем выбросить снова. Глобальный обработчик исключений будет обрабатывать это исключение и регистрировать его.

<?php

try {
$methodThatThrowsException();
}
catch (CriticalException $e) {
// do some stuff like cleanup/transaction rollback
throw $e;
}

Невосстановимые исключения

Если вы хотите просто зарегистрировать исключение и потерпеть неудачу, вы можете просто выбросить это исключение, и глобальный обработчик исключений перехватит и зарегистрирует его.

<?php

$methodThatThrowsException();

// ExceptionHandler::handle will be executed
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]