我正在开发一个 PHP 项目,其中我正在使用 Monolog 捕获异常并记录错误,并将友好的页面作为响应返回。
由于该项目目前处于早期阶段,因此我只是将错误记录到一个应用程序目录以外、公众无法访问的文件中,使用 Monolog 的 StreamHandler 类,随着项目的进展,我意识到如果出现某种IO错误,则可能会失败,因此我还将记录到数据库(可能是ElasticSearch)并发送关键错误消息给管理员。
由于我使用了StreamHandler,所以如果它无法打开文件,我可以看到它会引发异常。
现在,我应该如何处理这种情况下的异常,如果日志记录机制本身失败,我应该如何记录它?
我可以让另一个记录器处理异常,在这种关键情况下发送电子邮件,但问题又来了,如果邮件程序抛出异常,我该如何处理呢?
我认为页面将充满太多的try-catch块,而日志记录器散布在整个页面上看起来非常丑陋。
是否有一种优雅、简洁的解决方案,在大型项目中不涉及过多嵌套的try-catch块?(不流行的意见也欢迎)
以下是参考代码:
由于该项目目前处于早期阶段,因此我只是将错误记录到一个应用程序目录以外、公众无法访问的文件中,使用 Monolog 的 StreamHandler 类,随着项目的进展,我意识到如果出现某种IO错误,则可能会失败,因此我还将记录到数据库(可能是ElasticSearch)并发送关键错误消息给管理员。
由于我使用了StreamHandler,所以如果它无法打开文件,我可以看到它会引发异常。
现在,我应该如何处理这种情况下的异常,如果日志记录机制本身失败,我应该如何记录它?
我可以让另一个记录器处理异常,在这种关键情况下发送电子邮件,但问题又来了,如果邮件程序抛出异常,我该如何处理呢?
我认为页面将充满太多的try-catch块,而日志记录器散布在整个页面上看起来非常丑陋。
是否有一种优雅、简洁的解决方案,在大型项目中不涉及过多嵌套的try-catch块?(不流行的意见也欢迎)
以下是参考代码:
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();
}
}