Skip to content

Commit

Permalink
Add logging to error rendering failures
Browse files Browse the repository at this point in the history
When error rendering fails it can be tedious to diagnose what the
problem is. Having some logging when rendering fails could help triage
the problem and get to a solution quicker.

Refs #17603
  • Loading branch information
markstory committed Mar 10, 2024
1 parent 3f26c5b commit bcacc66
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 3 deletions.
19 changes: 19 additions & 0 deletions src/Error/Renderer/WebExceptionRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use Cake\Http\ResponseEmitter;
use Cake\Http\ServerRequest;
use Cake\Http\ServerRequestFactory;
use Cake\Log\Log;
use Cake\Routing\Exception\MissingRouteException;
use Cake\Routing\Router;
use Cake\Utility\Inflector;
Expand Down Expand Up @@ -161,6 +162,7 @@ protected function _getController(): Controller
$request = $request->withAttribute('params', $routerRequest->getAttribute('params'));
}

$class = "";

Check failure on line 165 in src/Error/Renderer/WebExceptionRenderer.php

View workflow job for this annotation

GitHub Actions / Coding Standard & Static Analysis

Use single instead of double quotes for simple strings.
try {
$params = $request->getAttribute('params');
$params['controller'] = 'Error';
Expand All @@ -185,6 +187,11 @@ protected function _getController(): Controller
$controller = new $class($request);
$controller->startupProcess();
} catch (Throwable $e) {
Log::warning(
"Failed to construct or call startup() on the resolved controller class of `$class`. " .
"Using Fallback Controller instead. Error {$e->getMessage()}",
'cake.error'
);
$controller = null;
}

Expand Down Expand Up @@ -412,6 +419,10 @@ protected function _outputMessage(string $template): Response

return $this->_shutdown();
} catch (MissingTemplateException $e) {
Log::warning(
"MissingTemplateException - Failed to render error template `{$template}`. Error: {$e->getMessage()}",
'cake.error'
);
$attributes = $e->getAttributes();
if (
$e instanceof MissingLayoutException ||
Expand All @@ -422,13 +433,21 @@ protected function _outputMessage(string $template): Response

return $this->_outputMessage('error500');
} catch (MissingPluginException $e) {
Log::warning(
"MissingPluginException - Failed to render error template `{$template}`. Error: {$e->getMessage()}",
'cake.error'
);
$attributes = $e->getAttributes();
if (isset($attributes['plugin']) && $attributes['plugin'] === $this->controller->getPlugin()) {
$this->controller->setPlugin(null);
}

return $this->_outputMessageSafe('error500');
} catch (Throwable $outer) {
Log::warning(
"Throwable - Failed to render error template `{$template}`. Error: {$outer->getMessage()}",
'cake.error'
);
try {
return $this->_outputMessageSafe('error500');
} catch (Throwable $inner) {
Expand Down
1 change: 1 addition & 0 deletions templates/Error/missing_controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
$namespace = Configure::read('App.namespace');
$prefixNs = $prefixPath = '';

$controller = (string)$controller;
$incompleteInflection = (str_contains($controller, '_') || str_contains($controller, '-'));
$originalClass = $controller;

Expand Down
3 changes: 2 additions & 1 deletion tests/TestCase/Error/ExceptionTrapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ public function testSkipLogException(): void
ob_get_clean();

$logs = Log::engine('test_error')->read();
$this->assertEmpty($logs);
$this->assertCount(1, $logs);
$this->assertStringContainsString('MissingTemplateException - Failed to render', $logs[0]);
$this->assertTrue($this->triggered, 'Should have triggered event when skipping logging.');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public function testHandleExceptionLogAttributes(): void
$request = ServerRequestFactory::fromGlobals();
$middleware = new ErrorHandlerMiddleware(['log' => true]);
$handler = new TestRequestHandler(function (): void {
throw new MissingControllerException(['class' => 'Articles']);
throw new MissingControllerException(['controller' => 'Articles']);
});
$result = $middleware->process($request, $handler);
$this->assertSame(404, $result->getStatusCode());
Expand All @@ -329,7 +329,7 @@ public function testHandleExceptionLogAttributes(): void
$logs[0]
);
$this->assertStringContainsString('Exception Attributes:', $logs[0]);
$this->assertStringContainsString("'class' => 'Articles'", $logs[0]);
$this->assertStringContainsString("'controller' => 'Articles'", $logs[0]);
$this->assertStringContainsString('Request URL:', $logs[0]);
}

Expand Down

0 comments on commit bcacc66

Please sign in to comment.