From 6e7fc11ee2b714348415c61ae587bf7039bb580f Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Mon, 16 Nov 2020 17:39:18 +0000
Subject: [PATCH] Issue #2949419 by mfb, vsujeetkumar, gapple, Hardik_Patel_12,
 neclimdul, dawehner, Sam152, xjm, alexpott: Pass the raw exception to logger
 implementations

---
 core/includes/errors.inc                      | 26 ++++++++++---------
 core/includes/update.inc                      |  5 ++--
 .../FinalExceptionSubscriber.php              |  3 +--
 core/lib/Drupal/Core/Utility/Error.php        |  3 ++-
 core/modules/dblog/src/Logger/DbLog.php       |  4 +--
 .../Tests/Core/Error/DrupalLogErrorTest.php   |  1 +
 6 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/core/includes/errors.inc b/core/includes/errors.inc
index 23ed7d4bb788..62179edf63ce 100644
--- a/core/includes/errors.inc
+++ b/core/includes/errors.inc
@@ -79,6 +79,7 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line) {
       'severity_level' => $severity_level,
       'backtrace' => $backtrace,
       '@backtrace_string' => (new \Exception())->getTraceAsString(),
+      'exception' => NULL,
     ], $recoverable || $to_string);
   }
   // If the site is a test site then fail for user deprecations so they can be
@@ -133,10 +134,12 @@ function error_displayable($error = NULL) {
  * Logs a PHP error or exception and displays an error page in fatal cases.
  *
  * @param $error
- *   An array with the following keys: %type, @message, %function, %file,
- *   %line, @backtrace_string, severity_level, and backtrace. All the parameters
- *   are plain-text, with the exception of @message, which needs to be an HTML
- *   string, and backtrace, which is a standard PHP backtrace.
+ *   An array with the following keys: %type, @message, %function, %file, %line,
+ *   @backtrace_string, severity_level, backtrace, and exception. All the
+ *   parameters are plain-text, with the exception of @message, which needs to
+ *   be an HTML string, backtrace, which is a standard PHP backtrace, and
+ *   exception, which is the exception object (or NULL if the error is not an
+ *   exception).
  * @param bool $fatal
  *   TRUE for:
  *   - An exception is thrown and not caught by something else.
@@ -146,13 +149,12 @@ function error_displayable($error = NULL) {
 function _drupal_log_error($error, $fatal = FALSE) {
   $is_installer = InstallerKernel::installationAttempted();
 
-  // Remove 'severity_level' as is not a valid replacement for t().
-  $severity = $error['severity_level'];
-  unset($error['severity_level']);
-
-  // Backtrace array is not a valid replacement value for t().
+  // Backtrace, exception and 'severity_level' are not valid replacement values
+  // for t().
   $backtrace = $error['backtrace'];
-  unset($error['backtrace']);
+  $exception = $error['exception'];
+  $severity = $error['severity_level'];
+  unset($error['backtrace'], $error['exception'], $error['severity_level']);
 
   // When running inside the testing framework, we relay the errors
   // to the tested site by the way of HTTP headers.
@@ -167,10 +169,10 @@ function _drupal_log_error($error, $fatal = FALSE) {
   // installer.
   if (\Drupal::hasService('logger.factory')) {
     try {
-      // Provide the PHP backtrace to logger implementations. Add
+      // Provide the PHP backtrace and exception to logger implementations. Add
       // 'severity_level' to the context to maintain BC and allow logging
       // implementations to use it.
-      \Drupal::logger('php')->log($severity, '%type: @message in %function (line %line of %file) @backtrace_string.', $error + ['backtrace' => $backtrace, 'severity_level' => $severity]);
+      \Drupal::logger('php')->log($severity, '%type: @message in %function (line %line of %file) @backtrace_string.', $error + ['backtrace' => $backtrace, 'exception' => $exception, 'severity_level' => $severity]);
     }
     catch (\Exception $e) {
       // We can't log, for example because the database connection is not
diff --git a/core/includes/update.inc b/core/includes/update.inc
index bea0c861e37a..d5818d005aaa 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -231,8 +231,7 @@ function update_do_one($module, $number, $dependency_map, &$context) {
       watchdog_exception('update', $e);
 
       $variables = Error::decodeException($e);
-      unset($variables['backtrace']);
-      unset($variables['severity_level']);
+      unset($variables['backtrace'], $variables['exception'], $variables['severity_level']);
       $ret['#abort'] = ['success' => FALSE, 'query' => t('%type: @message in %function (line %line of %file).', $variables)];
     }
   }
@@ -299,7 +298,7 @@ function update_invoke_post_update($function, &$context) {
       watchdog_exception('update', $e);
 
       $variables = Error::decodeException($e);
-      unset($variables['backtrace']);
+      unset($variables['backtrace'], $variables['exception']);
       $ret['#abort'] = [
         'success' => FALSE,
         'query' => t('%type: @message in %function (line %line of %file).', $variables),
diff --git a/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php
index a2a09ecf54c9..87d716932296 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php
@@ -93,8 +93,7 @@ public function onException(ExceptionEvent $event) {
 
       $error = $this->simplifyFileInError($error);
 
-      unset($error['backtrace']);
-      unset($error['severity_level']);
+      unset($error['backtrace'], $error['exception'], $error['severity_level']);
 
       if (!$this->isErrorLevelVerbose()) {
         // Without verbose logging, use a simple message.
diff --git a/core/lib/Drupal/Core/Utility/Error.php b/core/lib/Drupal/Core/Utility/Error.php
index 092f7626e210..306486ed7a56 100644
--- a/core/lib/Drupal/Core/Utility/Error.php
+++ b/core/lib/Drupal/Core/Utility/Error.php
@@ -71,6 +71,7 @@ public static function decodeException($exception) {
       'severity_level' => static::ERROR,
       'backtrace' => $backtrace,
       '@backtrace_string' => $exception->getTraceAsString(),
+      'exception' => $exception,
     ];
   }
 
@@ -86,7 +87,7 @@ public static function decodeException($exception) {
   public static function renderExceptionSafe($exception) {
     $decode = static::decodeException($exception);
     $backtrace = $decode['backtrace'];
-    unset($decode['backtrace']);
+    unset($decode['backtrace'], $decode['exception']);
     // Remove 'main()'.
     array_shift($backtrace);
 
diff --git a/core/modules/dblog/src/Logger/DbLog.php b/core/modules/dblog/src/Logger/DbLog.php
index 5933e222810c..4207a5c9db09 100644
--- a/core/modules/dblog/src/Logger/DbLog.php
+++ b/core/modules/dblog/src/Logger/DbLog.php
@@ -53,8 +53,8 @@ public function __construct(Connection $connection, LogMessageParserInterface $p
    * {@inheritdoc}
    */
   public function log($level, $message, array $context = []) {
-    // Remove any backtraces since they may contain an unserializable variable.
-    unset($context['backtrace']);
+    // Remove backtrace and exception since they may contain an unserializable variable.
+    unset($context['backtrace'], $context['exception']);
 
     // Convert PSR3-style messages to \Drupal\Component\Render\FormattableMarkup
     // style, so they can be translated too in runtime.
diff --git a/core/tests/Drupal/Tests/Core/Error/DrupalLogErrorTest.php b/core/tests/Drupal/Tests/Core/Error/DrupalLogErrorTest.php
index a867cd196b0a..40103f08abba 100644
--- a/core/tests/Drupal/Tests/Core/Error/DrupalLogErrorTest.php
+++ b/core/tests/Drupal/Tests/Core/Error/DrupalLogErrorTest.php
@@ -35,6 +35,7 @@ public function testFatalExitCode() {
   '@backtrace_string' => 'backtrace',
   'severity_level' => 0,
   'backtrace' => [],
+  'exception' => NULL,
 ];
 _drupal_log_error($error, TRUE);
 EOT;
-- 
GitLab