Skip to content
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

feat: reduce jserrors wrapping and remove onerror use #614

Merged
merged 2 commits into from
Jul 14, 2023

Conversation

patrickhousley
Copy link
Contributor

Replaces the use of the onerror global function with addEventListener to capture errors that go unhandled by customer code. This does not change how unhandled promise rejects are captured. Additional wrappings for events, timers, and animation fames have been removed in favor of capturing unhandled errors using a global event listener.

Overview

This PR removes wrappings for events, timers, and animation frames from the jserrors feature. Those wrappings are not specifically necessary unless another feature (spa) needs and performs the wrapping.

Errors are now primarily captured using a global event handler for error and unhandledrejection events. These events are captured and, if necessary, converted to Error-like objects that can be processed by the aggregator. This removes the use of the global onerror function and removes the need for customer's to not override our onerror function.

The jserrors feature retains a listener on the event emitter for fn-err events. In the event the spa feature is loaded, this handler will capture the error earlier than the global error handlers allowing for the spa feature to properly decorate the error with interaction data.

Related Issue(s)

https://issues.newrelic.com/browse/NR-138375

Testing

All the test cases should still pass with this change.

@patrickhousley patrickhousley added small Small Engineering Effort standalone A standalone effort (not planned for in an MMF) labels Jul 13, 2023
@github-actions
Copy link

github-actions bot commented Jul 13, 2023

Static Badge

Last ran on July 13, 2023 14:26:56 CDT
Checking merge of (ddfcbbb) into main (8a6f319)

@github-actions
Copy link

github-actions bot commented Jul 13, 2023

Asset Size Report

Merging this pull request will result in the following CDN asset size changes:

Asset Name Previous Size New Size Diff
nr-loader-spa.min 50.61 kB / 17.25 kB (gzip) 49.66 kB / 16.92 kB (gzip) -1.88% / -1.89% (gzip)
nr-loader-full.min 44.69 kB / 15.47 kB (gzip) 43.22 kB / 14.96 kB (gzip) -3.28% / -3.35% (gzip)
nr-loader-rum.min 26.53 kB / 9.72 kB (gzip) 26.49 kB / 9.71 kB (gzip) -0.12% / -0.11% (gzip)
nr-loader-spa-polyfills.min 123.15 kB / 39.36 kB (gzip) 122.53 kB / 39.08 kB (gzip) -0.5% / -0.7% (gzip)
nr-loader-full-polyfills.min 115.66 kB / 37.43 kB (gzip) 114.52 kB / 36.99 kB (gzip) -0.99% / -1.18% (gzip)
nr-loader-rum-polyfills.min 94.62 kB / 31.24 kB (gzip) 94.58 kB / 31.24 kB (gzip) -0.03% / -0.01% (gzip)
nr-loader-worker.min 41.24 kB / 14.2 kB (gzip) 39.78 kB / 13.68 kB (gzip) -3.54% / -3.66% (gzip)

Merging this pull request will result in the following NPM package consumer size changes:

Asset Name Previous Size New Size Diff
Browser Agent 50.75 kB / 17.13 kB (gzip) 49.79 kB / 16.8 kB (gzip) -1.88% / -1.94% (gzip)
Custom Lite Agent 26.68 kB / 9.64 kB (gzip) 26.64 kB / 9.63 kB (gzip) -0.12% / -0.08% (gzip)
Custom Pro Agent 44.75 kB / 15.29 kB (gzip) 43.28 kB / 14.78 kB (gzip) -3.3% / -3.34% (gzip)
Custom SPA Agent 50.63 kB / 17.09 kB (gzip) 49.68 kB / 16.76 kB (gzip) -1.89% / -1.94% (gzip)
Worker Agent 303.96 kB / 94.23 kB (gzip) 302.49 kB / 93.72 kB (gzip) -0.48% / -0.54% (gzip)
Other Standard CDN Assets

Released Assets

Asset Name Asset Size
recorder.1b18459f.min.js 166.07 kB / 52.32 kB (gzip)
spa-aggregate.e6b09d52.min.js 20.93 kB / 7.42 kB (gzip)
page_view_timing-aggregate.bd6de33a.min.js 14.97 kB / 5.43 kB (gzip)
860.2d6ff735.min.js 14.36 kB / 5.33 kB (gzip)
session_trace-aggregate.bb839bab.min.js 12.24 kB / 4.52 kB (gzip)
page_view_event-aggregate.cced4cf0.min.js 11.1 kB / 4.18 kB (gzip)
jserrors-aggregate.49e41428.min.js 9.58 kB / 3.67 kB (gzip)
metrics-aggregate.3dc53903.min.js 8.56 kB / 2.93 kB (gzip)
148.1a20d5fe.min.js 7.89 kB / 3.29 kB (gzip)
session_replay-aggregate.cf0efb30.min.js 7.28 kB / 2.75 kB (gzip)
ajax-aggregate.998ef92b.min.js 7.13 kB / 3.06 kB (gzip)
compressor.ae9f91a8.min.js 7.09 kB / 3.57 kB (gzip)
page_action-aggregate.ac76d497.min.js 4.73 kB / 1.92 kB (gzip)
async-api.30bd804e.min.js 2.92 kB / 1.46 kB (gzip)
session-manager.2a64278a.min.js 1.47 kB / 740 B (gzip)
lazy-feature-loader.0ba331d7.min.js 1.17 kB / 499 B (gzip)

Built Assets

Asset Name Asset Size
recorder.1b18459f.min.js 166.07 kB / 52.32 kB (gzip)
spa-aggregate.e6b09d52.min.js 20.93 kB / 7.42 kB (gzip)
page_view_timing-aggregate.bd6de33a.min.js 14.97 kB / 5.43 kB (gzip)
860.e349dcb2.min.js 14.09 kB / 5.27 kB (gzip)
session_trace-aggregate.bb839bab.min.js 12.24 kB / 4.52 kB (gzip)
page_view_event-aggregate.cced4cf0.min.js 11.1 kB / 4.18 kB (gzip)
jserrors-aggregate.a9ce8d9e.min.js 9.55 kB / 3.65 kB (gzip)
metrics-aggregate.3dc53903.min.js 8.56 kB / 2.93 kB (gzip)
148.1a20d5fe.min.js 7.89 kB / 3.29 kB (gzip)
session_replay-aggregate.cf0efb30.min.js 7.28 kB / 2.75 kB (gzip)
ajax-aggregate.998ef92b.min.js 7.13 kB / 3.06 kB (gzip)
compressor.ae9f91a8.min.js 7.09 kB / 3.57 kB (gzip)
page_action-aggregate.ac76d497.min.js 4.73 kB / 1.92 kB (gzip)
async-api.30bd804e.min.js 2.92 kB / 1.46 kB (gzip)
session-manager.2a64278a.min.js 1.47 kB / 740 B (gzip)
lazy-feature-loader.0ba331d7.min.js 1.17 kB / 499 B (gzip)
Other Polyfill CDN Assets

Released Assets

Asset Name Asset Size
recorder.1b18459f-es5.min.js 166.76 kB / 52.35 kB (gzip)
nr-polyfills.min.js 52.15 kB / 17.95 kB (gzip)
session_trace-aggregate.c836d31f-es5.min.js 32.26 kB / 8.5 kB (gzip)
compressor.79fb47d9-es5.min.js 30.02 kB / 11.29 kB (gzip)
spa-aggregate.9c283051-es5.min.js 24.02 kB / 8.11 kB (gzip)
page_view_timing-aggregate.79543323-es5.min.js 18.67 kB / 6.17 kB (gzip)
session_replay-aggregate.f4bdc759-es5.min.js 18.57 kB / 6.35 kB (gzip)
173.4c1277b2-es5.min.js 17.69 kB / 6.21 kB (gzip)
page_view_event-aggregate.f50d77d0-es5.min.js 12.64 kB / 4.8 kB (gzip)
jserrors-aggregate.d9f1a3f3-es5.min.js 12.38 kB / 4.42 kB (gzip)
ajax-aggregate.0812b00e-es5.min.js 10.58 kB / 3.78 kB (gzip)
646.abc32154-es5.min.js 10.41 kB / 4.1 kB (gzip)
metrics-aggregate.5092580c-es5.min.js 9.91 kB / 3.35 kB (gzip)
page_action-aggregate.b73fecd7-es5.min.js 7.33 kB / 2.64 kB (gzip)
async-api.2b4763c8-es5.min.js 4.16 kB / 1.99 kB (gzip)
session-manager.ae4f9cf3-es5.min.js 1.7 kB / 785 B (gzip)
lazy-feature-loader.fe02c936-es5.min.js 1.2 kB / 509 B (gzip)

Built Assets

Asset Name Asset Size
recorder.1b18459f-es5.min.js 166.76 kB / 52.35 kB (gzip)
nr-polyfills.min.js 52.15 kB / 17.95 kB (gzip)
session_trace-aggregate.c836d31f-es5.min.js 32.26 kB / 8.5 kB (gzip)
compressor.79fb47d9-es5.min.js 30.02 kB / 11.29 kB (gzip)
spa-aggregate.9c283051-es5.min.js 24.02 kB / 8.11 kB (gzip)
page_view_timing-aggregate.79543323-es5.min.js 18.67 kB / 6.17 kB (gzip)
session_replay-aggregate.f4bdc759-es5.min.js 18.57 kB / 6.35 kB (gzip)
173.71bbedb0-es5.min.js 17.41 kB / 6.14 kB (gzip)
page_view_event-aggregate.f50d77d0-es5.min.js 12.64 kB / 4.8 kB (gzip)
jserrors-aggregate.997fa838-es5.min.js 12.33 kB / 4.4 kB (gzip)
ajax-aggregate.0812b00e-es5.min.js 10.58 kB / 3.78 kB (gzip)
646.abc32154-es5.min.js 10.41 kB / 4.1 kB (gzip)
metrics-aggregate.5092580c-es5.min.js 9.91 kB / 3.35 kB (gzip)
page_action-aggregate.b73fecd7-es5.min.js 7.33 kB / 2.64 kB (gzip)
async-api.2b4763c8-es5.min.js 4.16 kB / 1.99 kB (gzip)
session-manager.ae4f9cf3-es5.min.js 1.7 kB / 785 B (gzip)
lazy-feature-loader.fe02c936-es5.min.js 1.2 kB / 509 B (gzip)

@codecov
Copy link

codecov bot commented Jul 13, 2023

Codecov Report

Merging #614 (ddfcbbb) into main (8a6f319) will decrease coverage by 0.11%.
The diff coverage is 0.00%.

@@            Coverage Diff             @@
##             main     #614      +/-   ##
==========================================
- Coverage   67.01%   66.90%   -0.11%     
==========================================
  Files         129      130       +1     
  Lines        5990     5965      -25     
  Branches     1140     1134       -6     
==========================================
- Hits         4014     3991      -23     
- Misses       1606     1608       +2     
+ Partials      370      366       -4     
Flag Coverage Δ
jest-component 21.08% <0.00%> (+0.09%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
...features/jserrors/aggregate/compute-stack-trace.js 86.88% <ø> (+0.70%) ⬆️
src/features/jserrors/instrument/index.js 18.18% <0.00%> (-24.13%) ⬇️
src/features/jserrors/instrument/uncaught-error.js 0.00% <0.00%> (ø)
src/loaders/api/api.js 67.22% <0.00%> (ø)

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@patrickhousley
Copy link
Contributor Author

Tests pass with expected safari 15 errors.

@patrickhousley patrickhousley merged commit e393c96 into main Jul 14, 2023
31 of 35 checks passed
@patrickhousley patrickhousley deleted the jserrors-unwrap branch July 14, 2023 14:30
@@ -183,6 +179,7 @@ testDriver.test('string error in custom tracer', function (t, browser, router) {
var nodeId = interactionTree.children[0].nodeId

var error = errors[0]
console.log(JSON.stringify(error))
Copy link
Contributor

Choose a reason for hiding this comment

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

remnant

import { InstrumentBase } from '../../utils/instrument-base'
import { FEATURE_NAME, NR_ERR_PROP } from '../constants'
import { FEATURE_NAME } from '../constants'
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you remove NR_ERR_PROP from the constants file too?

Comment on lines +74 to +76
if (typeof error.message !== 'undefined') {
return new UncaughtError(error.message, error.filename, error.lineno, error.colno)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a case when this is called with an error that's not an Error instance yet has a message?
I see fn-err and all internal-error events emitted with an actual error object from try-catch.

Copy link
Contributor

Choose a reason for hiding this comment

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

Likewise for castErrorEvent usage

Copy link
Contributor Author

Choose a reason for hiding this comment

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

throw can be passed any value.

function castReasonToError (reason) {
let prefix = 'Unhandled Promise Rejection: '
if (reason instanceof Error) {
if (typeof promiseRejectionEvent.reason === 'undefined') return new Error(prefix)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should keep in mind that when we create a new Error, the stack trace is going to point back to this code (us), so users will likely first come to us saying there's some error being thrown in our code.

That said, if they call reject() in promise without an arg, should this be more descriptive than just the prefix string?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This code was not changed, just moved. That said, I also questioned why we were creating new Error instances here for the same reason. I thought about changing this to use the UncaughtError class.

globalScope.addEventListener('error', (errorEvent) => {
if (!this.abortHandler) return
if (this.#seenErrors.has(errorEvent.error)) {
this.#seenErrors.delete(errorEvent.error)
Copy link
Contributor

Choose a reason for hiding this comment

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

would you mind adding a comment or some here about the process behind this / why it's done? for others

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
small Small Engineering Effort standalone A standalone effort (not planned for in an MMF)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants