Browse Source

Optionally include previous exception in log message if present

Marc Ypes 7 years ago
parent
commit
454f8d5873

+ 29 - 8
src/Error/Middleware/ErrorHandlerMiddleware.php

@@ -209,8 +209,32 @@ class ErrorHandlerMiddleware
      */
     protected function getMessage($request, $exception)
     {
+        $message = $this->getMessageForException($exception);
+
+        $message .= "\nRequest URL: " . $request->getRequestTarget();
+        $referer = $request->getHeaderLine('Referer');
+        if ($referer) {
+            $message .= "\nReferer URL: " . $referer;
+        }
+        if ($this->getConfig('trace')) {
+            $message .= "\nStack Trace:\n" . $exception->getTraceAsString() . "\n\n";
+        }
+
+        return $message;
+    }
+
+    /**
+     * Generate the message for the exception
+     *
+     * @param \Exception $exception The exception to log a message for.
+     * @param bool $isPrevious False for original exception, true for previous
+     * @return string Error message
+     */
+    protected function getMessageForException($exception, $isPrevious = false)
+    {
         $message = sprintf(
-            '[%s] %s',
+            '%s[%s] %s',
+            $isPrevious ? "\nPrevious: " : '',
             get_class($exception),
             $exception->getMessage()
         );
@@ -222,13 +246,10 @@ class ErrorHandlerMiddleware
                 $message .= "\nException Attributes: " . var_export($exception->getAttributes(), true);
             }
         }
-        $message .= "\nRequest URL: " . $request->getRequestTarget();
-        $referer = $request->getHeaderLine('Referer');
-        if ($referer) {
-            $message .= "\nReferer URL: " . $referer;
-        }
-        if ($this->getConfig('trace')) {
-            $message .= "\nStack Trace:\n" . $exception->getTraceAsString() . "\n\n";
+
+        $previous = $exception->getPrevious();
+        if ($previous) {
+            $message .= $this->getMessageForException($previous, true);
         }
 
         return $message;

+ 37 - 1
tests/TestCase/Error/Middleware/ErrorHandlerMiddlewareTest.php

@@ -178,7 +178,10 @@ class ErrorHandlerMiddlewareTest extends TestCase
                 $this->stringContains('[Cake\Http\Exception\NotFoundException] Kaboom!'),
                 $this->stringContains('ErrorHandlerMiddlewareTest->testHandleException'),
                 $this->stringContains('Request URL: /target/url'),
-                $this->stringContains('Referer URL: /other/path')
+                $this->stringContains('Referer URL: /other/path'),
+                $this->logicalNot(
+                    $this->stringContains('Previous: ')
+                )
             ));
 
         $request = ServerRequestFactory::fromGlobals([
@@ -197,6 +200,39 @@ class ErrorHandlerMiddlewareTest extends TestCase
     }
 
     /**
+     * Test rendering an error page logs errors with previous
+     *
+     * @return void
+     */
+    public function testHandleExceptionLogAndTraceWithPrevious()
+    {
+        $this->logger->expects($this->at(0))
+            ->method('log')
+            ->with('error', $this->logicalAnd(
+                $this->stringContains('[Cake\Http\Exception\NotFoundException] Kaboom!'),
+                $this->stringContains('Previous: [Cake\Datasource\Exception\RecordNotFoundException] Previous logged'),
+                $this->stringContains('ErrorHandlerMiddlewareTest->testHandleException'),
+                $this->stringContains('Request URL: /target/url'),
+                $this->stringContains('Referer URL: /other/path')
+            ));
+
+        $request = ServerRequestFactory::fromGlobals([
+            'REQUEST_URI' => '/target/url',
+            'HTTP_REFERER' => '/other/path'
+        ]);
+        $response = new Response();
+        $middleware = new ErrorHandlerMiddleware(null, ['log' => true, 'trace' => true]);
+        $next = function ($req, $res) {
+            $previous = new \Cake\Datasource\Exception\RecordNotFoundException('Previous logged');
+            throw new \Cake\Http\Exception\NotFoundException('Kaboom!', null, $previous);
+        };
+        $result = $middleware($request, $response, $next);
+        $this->assertNotSame($result, $response);
+        $this->assertEquals(404, $result->getStatusCode());
+        $this->assertContains('was not found', '' . $result->getBody());
+    }
+
+    /**
      * Test rendering an error page skips logging for specific classes
      *
      * @return void