Problem/Motivation

Sometime i get error / exception backtraces that lack newlines in the dblog html view.

Without patch:

Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\leaflet\LeafletService->leafletProcessGeofield() (line 141 of /var/www/html/web/modules/contrib/leaflet/src/LeafletService.php) #0 /var/www/html/web/modules/contrib/leaflet/leaflet_views/src/Plugin/views/style/LeafletMap.php(441): Drupal\leaflet\LeafletService->leafletProcessGeofield(Array) #1 /var/www/html/web/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php(2112): Drupal\leaflet_views\Plugin\views\style\LeafletMap->render(Array) #2 /var/www/html/web/core/modules/views/src/ViewExecutable.php(1530): Drupal\views\Plugin\views\display\DisplayPluginBase->render() #3 /var/www/html/web/core/modules/views/src/Plugin/views/display/Page.php(171): Drupal\views\ViewExecutable->render() #4 /var/www/html/web/core/modules/views/src/ViewExecutable.php(1627): Drupal\views\Plugin\views\display\Page->execute() #5 /var/www/html/web/core/modules/views/src/Element/View.php(77): Drupal\views\ViewExecutable->executeDisplay('page_1', Array) #6 [internal function]: Drupal\views\Element\View::preRenderViewElement(Array) #7 

With patch:

Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\leaflet\LeafletService->leafletProcessGeofield() (line 141 of /var/www/html/web/modules/contrib/leaflet/src/LeafletService.php).
#0 /var/www/html/web/modules/contrib/leaflet/leaflet_views/src/Plugin/views/style/LeafletMap.php(441): Drupal\leaflet\LeafletService->leafletProcessGeofield(Array)
#1 /var/www/html/web/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php(2112): Drupal\leaflet_views\Plugin\views\style\LeafletMap->render(Array)
#2 /var/www/html/web/core/modules/views/src/ViewExecutable.php(1530): Drupal\views\Plugin\views\display\DisplayPluginBase->render()
#3 /var/www/html/web/core/modules/views/src/Plugin/views/display/Page.php(171): Drupal\views\ViewExecutable->render()
#4 /var/www/html/web/core/modules/views/src/ViewExecutable.php(1627): Drupal\views\Plugin\views\display\Page->execute()
#5 /var/www/html/web/core/modules/views/src/Element/View.php(77): Drupal\views\ViewExecutable->executeDisplay('page_1', Array)
#6 [internal function]: Drupal\views\Element\View::preRenderViewElement(Array)
#7 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(378): call_user_func(Array, Array)

Proposed resolution

Add a

 tag to *all* backtraces (one source line already has).


Remaining tasks

Doit.

User interface changes

n/a

API changes

n/a

Data model changes

n/a
CommentFileSizeAuthor
#60 Screenshot-2019-12-16-09-40-22.png81.07 KBdagmar
#60 Screenshot-2019-12-16-09-40-22.png81.07 KBdagmar
#56 2930283-56.patch2.81 KBKrzysztof Domański
#56 interdiff-50-56.txt1.22 KBKrzysztof Domański
#50 2930283-50.patch2.66 KBKrzysztof Domański
#47 2930283-47.patch2.7 KBKrzysztof Domański
#47 interdiff-44-47.txt1.02 KBKrzysztof Domański
#44 2930283-44.patch2.78 KBKrzysztof Domański
#44 interdiff-42-44.txt1.56 KBKrzysztof Domański
#42 2930283-42.patch2.66 KBKrzysztof Domański
#42 interdiff-38-42.txt1.9 KBKrzysztof Domański
#38 2930283-38.patch2.48 KBKrzysztof Domański
#34 2930283-34.patch2.7 KBKrzysztof Domański
#34 interdiff-32-34.txt987 bytesKrzysztof Domański
#32 2930283-32.patch2.73 KBKrzysztof Domański
#32 interdiff-29-32.txt1.73 KBKrzysztof Domański
#31 Selection_655.png76.13 KBdagmar
#29 2930283-29.patch2.71 KBKrzysztof Domański
#29 2930283-test-only.patch1.91 KBKrzysztof Domański
#29 interdiff-26-29.txt2.77 KBKrzysztof Domański
#26 drupal-2930283-26-Error-backtrace.patch1.16 KBgeek-merlin
#21 drupal-2930283-21-Error-backtrace-.patch1.16 KBgeek-merlin
#17 error_backtrace.patch2.26 KBhi_ten_ja
#17 interdiff_error_backtrace.txt2.26 KBhi_ten_ja
#7 drupal-2930283-7-D8.4-Error-backtrace-malformat.patch3.16 KBgeek-merlin
#6 drupal-2930283-7-by-axel.rutz-Error-backtrace-malformat.patch3.23 KBgeek-merlin
#5 drupal-2930283-5-Show-new-error-log-in-dispatcher.patch3.23 KBgeek-merlin
#5 drupal-2930283-5-Show-previous-error-log-in-dispatcher.patch1.42 KBgeek-merlin
#2 drupal-2930283-2-Error-backtrace-malformat.patch2.07 KBgeek-merlin
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

axel.rutz created an issue. See original summary.

geek-merlin’s picture

Status: Active » Needs review
FileSize
2.07 KB

Changed all logs to use the same string, and all logger messages to use pre tag like already in verbose message codr branch.
(Interesting: The omissions are all on verrrry long code lines...)

Patch flying in that fixes this.

Status: Needs review » Needs work

The last submitted patch, 2: drupal-2930283-2-Error-backtrace-malformat.patch, failed testing. View results

geek-merlin’s picture

hmm ci dispatcher does 504, try later...

geek-merlin’s picture

Visualize errorlog diff:

Fixed from:

   [0] => [13-Dec-2017 19:13:56 UTC] Failed to log error: Exception: Deforestation in Drupal\error_service_test\MonkeysInTheControlRoom->handle() (line 59 of /var/www/html/core/modules/system/tests/modules/error_service_test/src/MonkeysInTheControlRoom.php). #0 /var/www/html/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\error_service_test\MonkeysInTheControlRoom->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)

    [1] => #1 /var/www/html/core/lib/Drupal/Core/DrupalKernel.php(657): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)

    [2] => #2 /var/www/html/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))

    [3] => #3 {main}

to

    [0] => [13-Dec-2017 20:37:41 UTC] Failed to log error: Exception: Deforestation in Drupal\error_service_test\MonkeysInTheControlRoom->handle() (line 59 of /var/www/html/core/modules/system/tests/modules/error_service_test/src/MonkeysInTheControlRoom.php).

    [1] => #0 /var/www/html/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\error_service_test\MonkeysInTheControlRoom->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)

    [2] => #1 /var/www/html/core/lib/Drupal/Core/DrupalKernel.php(657): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)

    [3] => #2 /var/www/html/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))

    [4] => #3 {main}
geek-merlin’s picture

geek-merlin’s picture

8.4 backport for those who like it.

geek-merlin’s picture

(mispost)

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

geek-merlin’s picture

Issue summary: View changes
geek-merlin’s picture

Issue summary: View changes
dawehner’s picture

Thank you for working on those improvements! They make a difference for some people :)

+++ b/core/includes/errors.inc
@@ -160,18 +160,20 @@ function _drupal_log_error($error, $fatal = FALSE) {
-      \Drupal::logger('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file) @backtrace_string.', $error + ['backtrace' => $backtrace]);
+      \Drupal::logger('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace_string</pre>', $error + ['backtrace' => $backtrace]);

It is a bit weird to log HTML to be honest. Can't we make it a bit more obvious by introducing new lines here too?

geek-merlin’s picture

> It is a bit weird to log HTML to be honest.

Yup. I thought that too but had no better idea.

> Can't we make it a bit more obvious by introducing new lines here too?

Can you elaborate (e.g. with a better patch ;-)?
\n? br-tag? Before the pre-tag? Remember that the pre tag is a block level tag.

hi_ten_ja’s picture

Status: Needs review » Needs work

The last submitted patch, 17: error_backtrace.patch, failed testing. View results

geek-merlin’s picture

#17: What's this? Looks like completely unrelated changes to me.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

geek-merlin’s picture

Patch flying in with a current 8.7 rebased version of #7 stripped down to a trivial oneliner.

I'm narrowing the scope to fix the annoying display of backtraces in dblog, so each line of the backtrace has one line, by simply adding a pre-tag around it. Fixing syslog can go to followups. Note that we already have HTML in that string, as the "%type" variable will be wrapped in em-tag, so no chance to bikeshed on that.

Let's get that in!

anruether’s picture

Status: Needs review » Reviewed & tested by the community

Looks good!

dagmar’s picture

Component: base system » dblog.module
Status: Reviewed & tested by the community » Needs work

Question, can we add this when displaying the log instead when saving it? I see a potential break in log parsers (other than provided by core) that expect to see %type: @message in %function (line %line of %file) @backtrace_string. and now they also find html inside.

> It is a bit weird to log HTML to be honest.

Yup. I thought that too but had no better idea.

I just tried this inside DbLogController::formatMessage() and seems to do the same thing. Also works for all error messages, not the new ones.

<?php
  public function formatMessage($row) {
    // Check for required properties.
    if (isset($row->message, $row->variables)) {
      $variables = @unserialize($row->variables);
      // Messages without variables or user specified text.
      if ($variables === NULL) {
        $message = Xss::filterAdmin($row->message);
      }
      elseif (!is_array($variables)) {
        $message = $this->t('Log data is corrupted and cannot be unserialized: @message', ['@message' => Xss::filterAdmin($row->message)]);
      }
      // Message to translate with injected variables.
      else {
        if ($row->message == '%type: @message in %function (line %line of %file) @backtrace_string.') {
          $row->message = '%type: @message in %function (line %line of %file) <pre class="backtrace">@backtrace_string</pre>.';
        }

        $message = $this->t(Xss::filterAdmin($row->message), $variables);
      }
    }
    else {
      $message = FALSE;
    }
    return $message;
  }
?>
geek-merlin’s picture

Component: dblog.module » base system
Status: Needs work » Reviewed & tested by the community

@dagmar #23:
It sounds very strange to me that people parse the HTML from the log, when they can swap out the error handler. (Do you do?)
They should know that HTML messages are not an API.

That said, if there's evidence that people do that i'd be all for a change note. Let's see what maintainer decides.

dagmar’s picture

Status: Reviewed & tested by the community » Needs work

@axel.rutz thanks for your comment.

It sounds very strange to me that people parse the HTML from the log, when they can swap out the error handler. (Do you do?)

I'm not saying they will parse html looking for logs. By changing that line you are basically affecting all loggers because they will now get a new error message with a new structure. We should try to minimize this type of changes if we can avoid them. For example people grepping syslog messages will not be able to do this anymore unless they notice this change.

Let's see what maintainer decides.

I cannot talk as core maintainer, but as current maintainer of the dblog and syslog modules I think it should be dblog responsibility to display the message properly. Even more when I shown in #23 is possible to do that without changing the log message structure.

If the main problem is that the dblog module is showing awful formatted back-traces, this seems more a visual fix than something to change when creating a log.

geek-merlin’s picture

Component: base system » dblog.module
Priority: Normal » Major
Status: Needs work » Needs review
FileSize
1.16 KB

OK thanks i did not realize this, so i'm taking this a maintainer verdict.
Patch flying in that implements #23. Maybe we get this finally in for 8.7.
Escalating to major as this bug makes the backtrace hard to read.

dagmar’s picture

Status: Needs review » Needs work

Thanks!. I would like to see a test that ensures this is working as expected.

Drupal\Tests\system\Functional\System\ErrorHandlerTest::testErrorHandler has some boilerplate you can use to trigger the exception and the code from Drupal\Tests\dblog\Functional\DbLogTest::testTemporaryUser() can be adapted to check the existence of the new <pre></pre> tags.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Krzysztof Domański’s picture

1. I added tests.

2. After adding the <pre></pre> tags, the dot displayed on a separate line at the end of the message. I moved the dot before backtrace.

#28 C:\drupal\core\lib\Drupal\Core\DrupalKernel.php(693): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#29 C:\drupal\index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#30 {main}
.

The last submitted patch, 29: 2930283-test-only.patch, failed testing. View results

dagmar’s picture

Issue summary: View changes
Status: Needs review » Needs work
FileSize
76.13 KB

This looks really good! Thanks @Krzysztof Domański

+++ b/core/modules/dblog/src/Controller/DbLogController.php
@@ -362,6 +362,10 @@ public function formatMessage($row) {
+        // Wrap backtraces from _drupal_log_error() in a pre tag.

I think the mention to _drupal_log_error should be removed here. Since this function may chance anytime (it is internal).

In my opinion it would be better to just say. "Ensure backtrace strings are properly formatted", or something similar.

I tested the functionality as is working as expected.

Krzysztof Domański’s picture

Status: Needs review » Needs work

The last submitted patch, 32: 2930283-32.patch, failed testing. View results

Krzysztof Domański’s picture

Status: Needs work » Needs review
FileSize
987 bytes
2.7 KB
dagmar’s picture

Status: Needs review » Reviewed & tested by the community

My concerns from #25, #27 and #31 are now addressed.

Thanks @Krzysztof Domański.

geek-merlin’s picture

Cool!

catch’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs re-roll

Needs a re-roll.

Krzysztof Domański’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
2.48 KB

Re-rolled. The code below has been added by #2228741: Replace calls to format_string() with Drupal\Component\Render\FormattableMarkup.

--- a/core/modules/dblog/tests/src/Functional/DbLogTest.php
+++ b/core/modules/dblog/tests/src/Functional/DbLogTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\dblog\Functional;
 
+use Drupal\Component\Render\FormattableMarkup;
Krzysztof Domański’s picture

Issue tags: -Needs re-roll
Anonymous’s picture

+1 rtbc

plach’s picture

Status: Reviewed & tested by the community » Needs work

Nice clean-up!

  1. +++ b/core/modules/dblog/src/Controller/DbLogController.php
    @@ -362,6 +362,10 @@ public function formatMessage($row) {
    +        if ($row->message == '%type: @message in %function (line %line of %file) @backtrace_string.') {
    

    Additionally, we could consider the plain %type: @message in %function (line %line of %file). message to cover also watchdog_exception().

    Anyway, it would be safer to ensure that $variables['@backtrace_string'] is set to avoid further notices. Setting NW for this.

    Also, minor: let's use === here.

  2. +++ b/core/modules/dblog/tests/src/Functional/DbLogTest.php
    @@ -787,4 +794,28 @@ public function testSameTimestampEntries() {
    +      '%function' => 'Drupal\error_test\Controller\ErrorTestController->generateWarnings()',
    

    We could use ErrorTestController::class here and concatenate it with ->generateWarnings().

Krzysztof Domański’s picture

Status: Needs work » Needs review
FileSize
1.9 KB
2.66 KB

@plach Thanks for feedback. I fixed #41.2.

it would be safer to ensure that $variables['@backtrace_string'] is set to avoid further notices

I think we should address this problem in a separate issue, because it is out of scope. We should only improve the display of error backtrace here. Can you open a new issue for #41.1?

plach’s picture

Thanks for the update!

+++ b/core/modules/dblog/src/Controller/DbLogController.php
@@ -362,6 +362,10 @@ public function formatMessage($row) {
+        if ($row->message === '%type: @message in %function (line %line of %file) @backtrace_string.') {

I don't think what I mentioned above is out of scope and thus deserves a new issue: the goal of this issue is to render backtraces correctly and watchdog_exception() is just another instance where the backtrace is rendered incorrectly (it's completely missing).

I mistakingly said that failing to check that @backtrace_string is set could trigger notices where in fact it wouldn't, however it would be a way to reinforce that we're actually dealing with the intended log event, since we're forced to check the message to recognize them. The added check would provide a bit more confidence that we are dealing with the intended case.

In short I'm proposing something like this:

if (isset($variables['@backtrace_string']) && preg_match('/%type: @message in %function \(line %line of %file\)( @backtrace_string)?./', $row->message)) {
  $row->message = '%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace_string</pre>';
}
Krzysztof Domański’s picture

plach’s picture

+++ b/core/modules/dblog/src/Controller/DbLogController.php
@@ -362,6 +362,11 @@ public function formatMessage($row) {
+        if (isset($variables['@backtrace_string']) && strpos($row->message, $message_with_backtrace) !== FALSE) {

This won't work with the watchdog_exception() message, which has a trailing dot instead of the @backtrace_string bit (see #41). If we want to avoid the regexp we could list the two supported messages explicitly and use in_array.

plach’s picture

Or we could do strpos($row->message, '%type: @message in %function (line %line of %file)') === 0.

Krzysztof Domański’s picture

plach’s picture

Status: Needs review » Reviewed & tested by the community

Looks good, thanks!

I wish there were a more reliable way to identify relevant log entries, however this is a nice improvement over the current situation.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Krzysztof Domański’s picture

longwave’s picture

Is it worth opening a separate issue to refactor %type: @message in %function (line %line of %file). to a constant somewhere? This string appears at least 15 times in the codebase.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 50: 2930283-50.patch, failed testing. View results

Krzysztof Domański’s picture

Status: Needs work » Reviewed & tested by the community

#52 Unrelated random test failure. Back to RTBC.

Spokje’s picture

Back to RTBC as per #48

Poor TestBot,
lost the plot,
created a fluke fail (so Needs Work this does not).

(Yes, it's "Sinterklaas" in The Netherlands on Dec. 5th, and you need to hand out stupid rhymes along with stupid gifts...)

EDIT: Meh, I'm way too slow for @Krzysztof Domański

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/dblog/src/Controller/DbLogController.php
@@ -362,6 +362,10 @@ public function formatMessage($row) {
+        // Ensure backtrace strings are properly formatted.
+        if (isset($variables['@backtrace_string']) && strpos($row->message, '%type: @message in %function (line %line of %file)') === 0) {
+          $row->message = '%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace_string</pre>';
+        }
         $message = $this->t(Xss::filterAdmin($row->message), $variables);

To preserve the translation and not to foist extra work on the translator I'd do this a bit differently. We can do:

        if (isset($variables['@backtrace_string'])) {
          $variables['@backtrace_string'] = new FormattableMarkup(
            '<pre class="backtrace">@backtrace_string</pre>', $variables
          );
         }

Also this means that the wherever @backtrace_string has been used in custom errors it'll now appear nicely as well. This code could do with a comment.

Krzysztof Domański’s picture

Status: Needs work » Needs review
FileSize
1.22 KB
2.81 KB
dagmar’s picture

Status: Needs review » Needs work

This code could do with a comment.

@Krzysztof Domański Thanks! I think the comment is missing

geek-merlin’s picture

#51;
> Is it worth opening a separate issue to refactor %type: @message in %function (line %line of %file). to a constant somewhere? This string appears at least 15 times in the codebase.

Yes, let us roll this home and address that cleanup in a separate issue. This is related to #2932518: Deprecate watchdog_exception which defines Error::DEFAULT_ERROR_MESSAGE and does:

-      watchdog_exception('Routing', $e);
+      \Drupal::logger('Routing')->error(Error::DEFAULT_ERROR_MESSAGE, Error::decodeException($e));
alexpott’s picture

Status: Needs work » Needs review

This code could do with a comment.

Actually looking at the current code I think it is good to go. All we need is an RTBC :)

dagmar’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
81.07 KB
81.07 KB

Tested locally. working as expected.

2930283 screenshot

alexpott’s picture

Version: 8.9.x-dev » 8.8.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)

Committed and pushed 010c63bc66 to 9.0.x and f52c5af6f5 to 8.9.x. Thanks!

Going to ask other committers about backporting this. It make reading errors in logs simpler which has to be a good thing.

  • alexpott committed 010c63b on 9.0.x
    Issue #2930283 by Krzysztof Domański, geek.merlin aka axel.rutz,...

  • alexpott committed f52c5af on 8.9.x
    Issue #2930283 by Krzysztof Domański, geek.merlin aka axel.rutz,...
Spokje’s picture

If the ancient Clan of Other Committers would decide on backporting this to D8.8 (which I really hope), patch #56 which was committed on D8.9 applies cleanly (and greenly) on the (current) latest D8.8.x-dev: https://www.drupal.org/pift-ci-job/1510080

alexpott’s picture

Status: Patch (to be ported) » Fixed

@catch +1'd the backport.

  • alexpott committed 9cbb20a on 8.8.x
    Issue #2930283 by Krzysztof Domański, geek.merlin aka axel.rutz,...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

geek-merlin’s picture