diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 4599b2b..c8c0f99 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -551,7 +551,10 @@ function _drupal_exception_handler($exception) {
 
   try {
     // Log the message to the watchdog and return an error page to the user.
-    _drupal_log_error(Error::decodeException($exception), TRUE);
+    $error = Error::decodeException($exception);
+    $error['@backtrace_string'] = $error['backtrace_string'];
+    unset($error['backtrace_string']);
+    _drupal_log_error($error, TRUE);
   }
   // PHP 7 introduces Throwable, which covers both Error and
   // Exception throwables.
diff --git a/core/includes/errors.inc b/core/includes/errors.inc
index b96b828..ed1f785 100644
--- a/core/includes/errors.inc
+++ b/core/includes/errors.inc
@@ -70,6 +70,7 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line, $c
     // in PHP, we allow them to trigger a fatal error by emitting a user error
     // using trigger_error().
     $to_string = $error_level == E_USER_ERROR && substr($caller['function'], -strlen('__toString()')) == '__toString()';
+    $e = new \Exception();
     _drupal_log_error(array(
       '%type' => isset($types[$error_level]) ? $severity_msg : 'Unknown error',
       // The standard PHP error handler considers that the error messages
@@ -80,6 +81,7 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line, $c
       '%line' => $caller['line'],
       'severity_level' => $severity_level,
       'backtrace' => $backtrace,
+      '@backtrace_string' => $e->getTraceAsString(),
     ), $recoverable || $to_string);
   }
 }
@@ -163,18 +165,18 @@ function _drupal_log_error($error, $fatal = FALSE) {
   // installer.
   if (\Drupal::hasService('logger.factory')) {
     try {
-      \Drupal::logger('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file).', $error);
+      \Drupal::logger('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file) @backtrace_string.', $error);
     }
     catch (\Exception $e) {
       // We can't log, for example because the database connection is not
       // available. At least try to log to PHP error log.
-      error_log(strtr('Failed to log error: %type: @message in %function (line %line of %file).', $error));
+      error_log(strtr('Failed to log error: %type: @message in %function (line %line of %file). @backtrace_string', $error));
     }
   }
 
   // Log fatal errors, so developers can find and debug them.
   if ($fatal) {
-    error_log(sprintf('%s: %s in %s on line %d', $error['%type'], $error['@message'], $error['%file'], $error['%line']));
+    error_log(sprintf('%s: %s in %s on line %d %s', $error['%type'], $error['@message'], $error['%file'], $error['%line'], $error['@backtrace_string']));
   }
 
   if (PHP_SAPI === 'cli') {
diff --git a/core/modules/system/src/Tests/System/UncaughtExceptionTest.php b/core/modules/system/src/Tests/System/UncaughtExceptionTest.php
index 0cc6862..c435bc6 100644
--- a/core/modules/system/src/Tests/System/UncaughtExceptionTest.php
+++ b/core/modules/system/src/Tests/System/UncaughtExceptionTest.php
@@ -253,7 +253,7 @@ public function testLoggerException() {
 
     // Find fatal error logged to the simpletest error.log
     $errors = file(\Drupal::root() . '/' . $this->siteDirectory . '/error.log');
-    $this->assertIdentical(count($errors), 2, 'The error + the error that the logging service is broken has been written to the error log.');
+    $this->assertIdentical(count($errors), 6, 'The error + the error that the logging service is broken has been written to the error log.');
     $this->assertTrue(strpos($errors[0], 'Failed to log error') !== FALSE, 'The error handling logs when an error could not be logged to the logger.');
 
     $expected_path = \Drupal::root() . '/core/modules/system/tests/modules/error_service_test/src/MonkeysInTheControlRoom.php';
