gpt4 book ai didi

php - 在处理另一个异常时,我应该如何处理记录器抛出的异常?

转载 作者:可可西里 更新时间:2023-10-31 23:00:37 24 4
gpt4 key购买 nike

我正在开发一个 PHP 项目,我在该项目中捕获异常并使用 Monolog 记录错误并返回一个用户友好的页面作为响应。

该项目目前处于婴儿阶段,所以我只是将错误记录到一个文件中,使用 Monolog 的 StreamHandler 类在公众无法访问的应用程序目录中,随着我的进步,我意识到这可能如果存在某种 IO 错误,则会失败,因此我还将登录到数据库(可能是 ElasticSearch)并通过电子邮件将严重错误发送给管理员。

当我使用 StreamHandler 时,我可以看到它在无法打开文件时抛出异常。

现在,我应该如何处理这种异常情况,如果日志机制本身失败,我应该如何记录它?

我可以让另一个记录器处理异常,该记录器会在这种紧急情况下发送电子邮件,但同样,我该如何处理邮件程序抛出的异常?

我假设该页面将充满太多 try-catch block ,记录器遍布整个页面,这看起来非常丑陋。

是否有一个优雅、干净的解决方案,不涉及在大型项目中使用的太多嵌套 try-catch block ? (不受欢迎的意见也欢迎)

这里有一些代码供引用:

try
{
$routes = require_once(__DIR__.'/Routes.php');

$router = new RouteFactory($routes, $request, \Skletter\View\ErrorPages::class);
$router->buildPaths('Skletter\Controller\\', 'Skletter\View\\');

$app = new Application($injector);
$app->run($request, $router);
}
catch (InjectionException | InvalidErrorPage | NoHandlerSpecifiedException $e)
{
$log = new Logger('Resolution');
try
{
$log->pushHandler(new StreamHandler(__DIR__ . '/../app/logs/error.log', Logger::CRITICAL));
$log->addCritical($e->getMessage(),
array(
'Stack Trace' => $e->getTraceAsString()
));
}
catch (Exception $e)
{
echo "No access to log file: ". $e->getMessage();
// Should I handle this exception by pushing to db or emailing?
// Can possibly introduce another nested try-catch block
}
finally
{
/**
* @var \Skletter\View\ErrorPageView $errorPage
*/
$errorPage = $injector->make(\Skletter\View\ErrorPages::class);
$errorPage->internalError($request)->send();
}
}

最佳答案

异常记录和异常通知是两个必须在整个项目中全局解决的任务。它们不应该用 help try-catch block 来解决,因为通常应该使用 try-catch 来尝试解决具体的局部定位问题,这使得异常(例如,修改数据或尝试重复执行)或执行恢复应用程序状态的操作。关于异常的日志记录和通知是应该使用全局异常处理程序来解决的任务。 PHP 具有使用 set_exception_handler 配置异常处理程序的 native 机制。功能。例如:

function handle_exception(Exception $exception)
{
//do something, for example, store an exception to log file
}

set_exception_handler('handle_exception');

配置处理程序后,所有抛出的异常都将使用handle_exception() 函数进行处理。例如:

function handle_exception(Exception $exception)
{
echo $exception->getMessage();
}

set_exception_handler('handle_exception');
// some code
throw Exception('Some error was happened');

此外,您始终可以使用 help restore_exception_handler 禁用当前异常处理程序功能。

在您的情况下,您可以创建一个简单的异常处理程序类,它将包含日志记录方法和通知方法,并实现一种机制来处理异常,该机制将选择必要的方法。例如:

class ExceptionHandler
{
/**
* Store an exception into a log file
* @param Exception $exception the exception that'll be sent
*/
protected function storeToLog(Exception $exception)
{}

/**
* Send an exception to the email address
* @param Exception $exception the exception that'll be sent
*/
protected function sendToEmail(Exception $exception)
{}

/**
* Do some other actions with an exception
* @param Exception $exception the exception that'll be handled
*/
protected function doSomething(Exception $exception)
{}

/**
* Handle an exception
* @param Exception $exception the exception that'll be handled
*/
public function handle(Exception $exception)
{
try {
// try to store the exception to log file
$this->storeToLog($exception);
} catch (Exception $exception) {
try {
// if the exception wasn't stored to log file
// then try to send the exception via email
$this->sendToEmail($exception);
} catch (Exception $exception) {
// if the exception wasn't stored to log file
// and wasn't send via email
// then try to do something else
$this->doSomething($exception);
}
}

}
}

之后就可以注册这个handler了

$handler = new ExceptionHandler();
set_exception_handler([$handler, 'handle']);


$routes = require_once(__DIR__.'/Routes.php');

$router = new RouteFactory($routes, $request, \Skletter\View\ErrorPages::class);
$router->buildPaths('Skletter\Controller\\', 'Skletter\View\\');

$app = new Application($injector);
$app->run($request, $router);

关于php - 在处理另一个异常时,我应该如何处理记录器抛出的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56849335/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com