I am working on a PHP project where I am catching exceptions and logging the errors using Monolog and returning a user-friendly page as a response.
The project is currently in its baby phases, so I am just logging the errors to a file using Monolog's StreamHandler
class in an app directory outside of the public's reach, as I progress I realize this may fail if there's an IO error of some sort and so I will also be logging to a database (possible ElasticSearch) and sending critical errors via email to the admin.
As I am using the StreamHandler
, I can see that it throws an exception if it fails to open the file.
Now, how should I be handling this case of exception and how should I log it if the logging mechanism itself fails?
I can have the exception be handled by another logger which sends an email on such critical situations, but again, how do I handle the exception being thrown by the mailer?
I assume the page would be filled with too many try-catch blocks with loggers spread out throughout the page which would look downright ugly.
Is there an elegant, clean solution that doesn't involve too many nested try-catch blocks that are being used in large scale projects? (Unpopular opinions are also welcome)
Here is some code for reference:
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();
}
}