Skip to content

fix(rum-core): capture stack trace from syntax errors properly #1239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 14, 2022
Merged

fix(rum-core): capture stack trace from syntax errors properly #1239

merged 1 commit into from
Jun 14, 2022

Conversation

devcorpio
Copy link
Contributor

@devcorpio devcorpio commented Jun 7, 2022

Context

The RUM agent was capturing errors thrown in inline scripts with an empty stack trace. There is a nuance to highlight, though.

This only affects to errors whose type is SyntaxError and have been triggered because of a malformed JavaScript code. This tend to occur when the browser is parsing the document.

The following two examples will help to understand that nuance:

Example 1 (KO): SyntaxError because of malformed JavaScript while parsing the document:

<html>
  <head>Example 1: SyntaxError because of malformed JavaScript while parsing the document </head>
  <body>
     Hello, I am Example 1 page.
    <script>
         var a:      // This throws a Syntax Error
    </script>
  </body>
</html>

As we can see on the screenshot below the stacktrace was empty:

Screenshot 2022-06-07 at 16 20 22

Example 2 (OK): SyntaxError because of bad usage of JSON.parse

<html>
  <head>Example 2: SyntaxError because of bad usage of JSON.parse </head>
  <body>
     Hello, I am Example 2 page.
    <script>
         JSON.parse("bad json") // this will throw a SyntaxError too
    </script>
  </body>
</html>

As we can see on the screenshot below the stack trace was not empty, since this kind of SyntaxError was being handled properly:

Screenshot 2022-06-07 at 16 26 53

How are we generating stacktraces?

One of the steps of the error capturing flow is the one that generates the stacktrace from an error event. Given the complexity that some cases have (cross browsing support for instance) we rely on a third-party library named error-stack-parser. Unfortunately, that case is not being handled as expected.

Fix

The ErrorEvent that the browser dispatches when an uncaught error takes place contains all the information we need to generate the stacktrace. So, that's what we do now, we create a stack trace of a single element which contains the missing information.

After the fix, the stacktrace of example 1 looks this way: 🎉

Screenshot 2022-06-07 at 16 48 43

Next

We are going to create an issue in the third-party library to report the unexpected behaviour.

Edit: issue created stacktracejs/error-stack-parser#81

@devcorpio devcorpio linked an issue Jun 7, 2022 that may be closed by this pull request
@apmmachine
Copy link
Contributor

📦 Bundlesize report

Filename Size(bundled) Size(gzip) Diff(gzip)
elastic-apm-opentracing.umd.min.js 65.8 KiB 21.0 KiB ⚠️ 26 Bytes
elastic-apm-rum.umd.min.js 59.7 KiB 19.4 KiB ⚠️ 37 Bytes

@apmmachine
Copy link
Contributor

💚 Build Succeeded

the below badges are clickable and redirect to their specific view in the CI or DOCS
Pipeline View Test View Changes Artifacts preview preview

Expand to view the summary

Build stats

  • Start Time: 2022-06-07T14:57:00.526+0000

  • Duration: 90 min 51 sec

Test stats 🧪

Test Results
Failed 0
Passed 4730
Skipped 62
Total 4792

🤖 GitHub comments

To re-run your PR in the CI, just comment with:

  • /test : Re-trigger the build.

  • run benchmark tests : Run the benchmark test.

  • run elasticsearch-ci/docs : Re-trigger the docs validation. (use unformatted text in the comment!)

@apmmachine
Copy link
Contributor

🌐 Coverage report

Name Metrics % (covered/total) Diff
Packages 100.0% (8/8) 💚
Files 98.148% (53/54) 👍 0.109
Classes 98.148% (53/54) 👍 0.109
Methods 97.406% (413/424) 👍 0.056
Lines 95.296% (2107/2211) 👎 -0.03
Conditionals 86.337% (1049/1215) 👎 -0.099

Copy link
Contributor

@kyungeunni kyungeunni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

return true
}

export function createStackTraces(stackParser, errorEvent) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it correct that we are now passing stackParser here in order to mock this library when testing? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that's right! 🎉 . In this particular scenario the option of injecting the dependency was the simplest strategy for making the testing experience smooth.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why you didnt go with mocking error-stack-parser using spy instead?

Copy link
Contributor Author

@devcorpio devcorpio Jun 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, with jasmine we cannot spy properly a third-party (node_modules one) dependency. Not with our project setup at least 😢

Copy link
Member

@vigneshshanmugam vigneshshanmugam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🎉 Good catch Alberto.

@devcorpio devcorpio merged commit 4081941 into elastic:main Jun 14, 2022
@devcorpio devcorpio deleted the inline_error branch June 14, 2022 10:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Inline scripts errors does not have any references.
4 participants