-
-
Notifications
You must be signed in to change notification settings - Fork 342
Fix: don't symbolicate console asserts that comes from metro. #4770
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
base: main
Are you sure you want to change the base?
Conversation
Android (legacy) Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
80b2ce3 | 385.02 ms | 387.36 ms | 2.34 ms |
8bda0cc | 450.38 ms | 433.89 ms | -16.49 ms |
457e29f | 398.10 ms | 421.39 ms | 23.29 ms |
7d161c0 | 413.02 ms | 435.29 ms | 22.26 ms |
ddc0552 | 472.92 ms | 460.66 ms | -12.26 ms |
07e58c9 | 495.04 ms | 489.73 ms | -5.31 ms |
950b04f | 433.92 ms | 462.43 ms | 28.51 ms |
3f05680 | 397.91 ms | 405.65 ms | 7.74 ms |
e73d82f | 475.82 ms | 506.55 ms | 30.73 ms |
2de79dc | 435.31 ms | 416.96 ms | -18.35 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
80b2ce3 | 17.73 MiB | 19.75 MiB | 2.02 MiB |
8bda0cc | 17.75 MiB | 20.11 MiB | 2.36 MiB |
457e29f | 17.73 MiB | 19.84 MiB | 2.10 MiB |
7d161c0 | 17.75 MiB | 20.12 MiB | 2.37 MiB |
ddc0552 | 17.74 MiB | 20.09 MiB | 2.35 MiB |
07e58c9 | 17.74 MiB | 20.08 MiB | 2.34 MiB |
950b04f | 17.75 MiB | 20.13 MiB | 2.38 MiB |
3f05680 | 17.75 MiB | 20.11 MiB | 2.37 MiB |
e73d82f | 17.73 MiB | 20.07 MiB | 2.33 MiB |
2de79dc | 17.75 MiB | 20.13 MiB | 2.38 MiB |
iOS (legacy) Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
484813b+dirty | 1222.45 ms | 1220.79 ms | -1.66 ms |
b6da94a+dirty | 1227.82 ms | 1238.86 ms | 11.04 ms |
60d7316+dirty | 1219.13 ms | 1221.74 ms | 2.61 ms |
9f0f6c8+dirty | 1231.60 ms | 1232.73 ms | 1.12 ms |
4a6664f+dirty | 1209.49 ms | 1208.63 ms | -0.86 ms |
b7e707e+dirty | 1220.48 ms | 1229.53 ms | 9.05 ms |
f80e57e+dirty | 1217.29 ms | 1230.61 ms | 13.32 ms |
0db0c72+dirty | 1275.02 ms | 1285.84 ms | 10.82 ms |
c639edf+dirty | 1236.18 ms | 1235.04 ms | -1.14 ms |
a15d370+dirty | 1214.69 ms | 1214.02 ms | -0.67 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
484813b+dirty | 2.36 MiB | 3.08 MiB | 734.18 KiB |
b6da94a+dirty | 2.63 MiB | 3.76 MiB | 1.13 MiB |
60d7316+dirty | 2.63 MiB | 3.74 MiB | 1.11 MiB |
9f0f6c8+dirty | 2.36 MiB | 3.10 MiB | 759.48 KiB |
4a6664f+dirty | 2.36 MiB | 3.04 MiB | 696.39 KiB |
b7e707e+dirty | 2.63 MiB | 3.76 MiB | 1.13 MiB |
f80e57e+dirty | 2.63 MiB | 3.78 MiB | 1.14 MiB |
0db0c72+dirty | 2.36 MiB | 2.84 MiB | 487.01 KiB |
c639edf+dirty | 2.36 MiB | 3.08 MiB | 736.63 KiB |
a15d370+dirty | 2.63 MiB | 3.76 MiB | 1.13 MiB |
Previous results on branch: lz/fix-console
Startup times
Revision | Plain | With Sentry | Diff |
---|---|---|---|
4fd28cc+dirty | 1214.26 ms | 1226.96 ms | 12.70 ms |
63aead8+dirty | 1207.92 ms | 1219.14 ms | 11.23 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
4fd28cc+dirty | 2.63 MiB | 3.78 MiB | 1.14 MiB |
63aead8+dirty | 2.63 MiB | 3.78 MiB | 1.14 MiB |
Android (new) Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
24cb2a4+dirty | 366.28 ms | 410.96 ms | 44.68 ms |
6e8584e+dirty | 383.37 ms | 400.84 ms | 17.47 ms |
8bda0cc+dirty | 383.08 ms | 417.40 ms | 34.32 ms |
13b68d9+dirty | 372.54 ms | 388.85 ms | 16.31 ms |
950b04f+dirty | 308.66 ms | 312.69 ms | 4.03 ms |
1d75738+dirty | 380.29 ms | 376.78 ms | -3.52 ms |
e2b64fe+dirty | 258.82 ms | 304.26 ms | 45.44 ms |
9672577+dirty | 391.55 ms | 412.57 ms | 21.02 ms |
80b2ce3+dirty | 271.29 ms | 316.47 ms | 45.18 ms |
3ffcddd+dirty | 244.82 ms | 295.47 ms | 50.65 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
24cb2a4+dirty | 7.15 MiB | 8.38 MiB | 1.23 MiB |
6e8584e+dirty | 7.15 MiB | 8.13 MiB | 1002.18 KiB |
8bda0cc+dirty | 7.15 MiB | 8.38 MiB | 1.23 MiB |
13b68d9+dirty | 7.15 MiB | 8.38 MiB | 1.23 MiB |
950b04f+dirty | 7.15 MiB | 8.40 MiB | 1.25 MiB |
1d75738+dirty | 7.15 MiB | 8.40 MiB | 1.25 MiB |
e2b64fe+dirty | 7.15 MiB | 8.07 MiB | 947.16 KiB |
9672577+dirty | 7.15 MiB | 8.38 MiB | 1.23 MiB |
80b2ce3+dirty | 7.15 MiB | 8.04 MiB | 911.02 KiB |
3ffcddd+dirty | 7.15 MiB | 8.04 MiB | 912.17 KiB |
iOS (new) Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
484813b+dirty | 1225.07 ms | 1221.00 ms | -4.07 ms |
b6da94a+dirty | 1219.33 ms | 1223.35 ms | 4.02 ms |
60d7316+dirty | 1224.33 ms | 1231.29 ms | 6.96 ms |
9f0f6c8+dirty | 1236.94 ms | 1245.41 ms | 8.47 ms |
4a6664f+dirty | 1218.77 ms | 1221.07 ms | 2.30 ms |
b7e707e+dirty | 1220.86 ms | 1225.53 ms | 4.67 ms |
f80e57e+dirty | 1226.92 ms | 1226.82 ms | -0.10 ms |
0db0c72+dirty | 1258.88 ms | 1262.52 ms | 3.64 ms |
c639edf+dirty | 1223.63 ms | 1227.98 ms | 4.35 ms |
a15d370+dirty | 1215.00 ms | 1214.75 ms | -0.25 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
484813b+dirty | 2.92 MiB | 3.64 MiB | 740.56 KiB |
b6da94a+dirty | 3.19 MiB | 4.33 MiB | 1.14 MiB |
60d7316+dirty | 3.19 MiB | 4.30 MiB | 1.12 MiB |
9f0f6c8+dirty | 2.92 MiB | 3.67 MiB | 771.98 KiB |
4a6664f+dirty | 2.92 MiB | 3.60 MiB | 702.09 KiB |
b7e707e+dirty | 3.19 MiB | 4.33 MiB | 1.14 MiB |
f80e57e+dirty | 3.19 MiB | 4.34 MiB | 1.16 MiB |
0db0c72+dirty | 2.92 MiB | 3.40 MiB | 492.71 KiB |
c639edf+dirty | 2.92 MiB | 3.64 MiB | 742.55 KiB |
a15d370+dirty | 3.19 MiB | 4.33 MiB | 1.14 MiB |
Previous results on branch: lz/fix-console
Startup times
Revision | Plain | With Sentry | Diff |
---|---|---|---|
4fd28cc+dirty | 1221.24 ms | 1226.67 ms | 5.43 ms |
63aead8+dirty | 1237.88 ms | 1232.57 ms | -5.31 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
4fd28cc+dirty | 3.19 MiB | 4.34 MiB | 1.16 MiB |
63aead8+dirty | 3.19 MiB | 4.35 MiB | 1.16 MiB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes LGTM 🎸
Thank you for the tests and the sample enhancement.
Added a nitpick suggestion on the sample UI.
Co-authored-by: Antonis Lilis <[email protected]>
The code looks good, do you have an example stack how the problematic assert gets called? Is it inside of the |
I actually have one here: LOG Assertion called: true message 'this' is expected an Event object, but got [{"isTrusted":false}] stack : Error
at getCurrentStackTrace (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:125938:26)
at anonymous (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:125950:57)
at apply (native)
at anonymous (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:154465:27)
at pd (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:36235:19)
at setPassiveListener (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:36640:7)
at dispatchEvent (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:36939:27)
at setReadyState (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:36129:27)
at open (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:36041:27)
at apply (native)
at anonymous (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:155583:34)
at anonymous (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:29261:17)
at tryCallTwo (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204678:9)
at doResolve (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204817:25)
at Promise (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204697:14)
at fetch (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:29218:25)
at ?anon_0_ (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28649:33)
at next (native)
at asyncGeneratorStep (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28665:26)
at _next (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28684:29)
at anonymous (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28689:14)
at tryCallTwo (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204678:9)
at doResolve (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204817:25)
at Promise (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204697:14)
at anonymous (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28681:25)
at apply (native)
at _symbolicateStackTrace (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28658:40)
at apply (native)
at symbolicateStackTrace (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28637:40)
at symbolicate (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28616:52)
at handleSymbolicate (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28516:42)
at symbolicate (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28507:33)
at appendNewLog (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28152:25)
at anonymous (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28196:21)
at apply (native)
at anonymous (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:35288:26)
at _callTimer (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:35167:17)
at _callReactNativeMicrotasksPass (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:35212:17)
at callReactNativeMicrotasks (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:35418:44)
at __callReactNativeMicrotasks (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:3569:48)
at anonymous (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:3342:45)
at __guard (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:3541:15)
at flushedQueue (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:3341:21)
at callFunctionReturnFlushedQueue (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:3326:33) It is indeed inside of Do you have any preference on where I could store this stack trace? |
Thank you for the stack. I think we can add this to a comment in the code. When looking at the stack I believe this is the most important part. It's no necessary the symbolication, but the underlying fetch call. This is the last frame in RN before the assert happens in the shims.
|
Looking at the cause the best solution would be to use a network request which calls This would mean vendoring the RN symbolicate function so we can replace the fetch with out own patched fetch which calls the XMLHttpRequest functions inside of the sandbox. The RN symbolicate fun calls fetch which calls the XMLHttpRequest. Let me know what do you think about that? |
That surely works better , I have applied your suggestion on cb9ef09 |
… into lz/fix-console
…react-native into lz/fix-console
(symbolicateStackTrace as jest.Mock).mockImplementation(() => { | ||
// eslint-disable-next-line no-console | ||
console.assert(false, 'should not be logged as an event', '<object>'); | ||
return Promise.resolve({ | ||
stack: [], | ||
} as ReactNative.SymbolicatedStackTrace); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also add a test where the assert is executed in the Promise. I believe that test would fail at the moment. Because only the code till the first await
statement will be in the sandbox.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That surely breaks the test :c
We are a bit limited on what we could do here since we don't have the control on when the console log is going to happen.
I have a code proposal where we implement a delayed console sandbox, where we can control when to start logging console events after the callback was finished:
export function delayedConsoleSandBox<T>(callback: () => T, timer: number): T {
if (!('console' in GLOBAL_OBJ)) {
return callback();
}
+++ let isPromise = false;
const console = GLOBAL_OBJ.console as Console;
const wrappedFuncs: Partial<LoggerConsoleMethods> = {};
const wrappedLevels = Object.keys(originalConsoleMethods) as ConsoleLevel[];
+++ const delayedRestore = () => {
+++ setTimeout(() => {
+++ // Revert restoration to wrapped state
+++ wrappedLevels.forEach(level => {
+++ console[level] = wrappedFuncs[level] as LoggerMethod;
+++ });
+++ }, timer);
+++ };
// Restore all wrapped console methods
wrappedLevels.forEach(level => {
const originalConsoleMethod = originalConsoleMethods[level] as LoggerMethod;
wrappedFuncs[level] = console[level] as LoggerMethod | undefined;
console[level] = originalConsoleMethod;
});
try {
const result = callback();
+++ if (result instanceof Promise) {
+++ isPromise = true;
+++ result.finally(() => delayedRestore());
+++ return result;
+++ }
+++ else {
return result;
+++ }
} finally {
+++ if (!isPromise) {
delayedRestore();
+++ }
}
}
What do you think @krystofwoldrich @antonis ? It's just the normal code with some support for promises and also a timeout for restoring the sandbox after the promise/function finishes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this would work, but I'm concerned about the fact, that all console log (not only the ones from the network call) will be in the sandbox until the network call (symbolication) resolves.
@lucas-zimerman @antonis Let me know what do you think, but to avoid a complex logic, since as @lucas-zimerman mention this is only for local builds, I would return to the original ignoring of the particular error causing issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more options that I think would be feasible is to Proxy all method calls of the XHR object https://github.com/facebook/react-native/blob/f0527d86623112eee1e80da7884081f7ecf59bea/packages/react-native/Libraries/Network/XMLHttpRequest.js#L82
so all of the method are executed in consoleSandbox, since they are all synchronous it should work nicely, not sandboxing anything outside of the network call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more options that I think would be feasible is to Proxy all method calls of the XHR object
That sounds like a good approach to me 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me, I will work on it
📢 Type of change
📜 Description
Adds a small patch to DebugSymbolicator that ignores events generated by metro.
💡 Motivation and Context
In short: when interacting with the metro bridge, React Native uses the following code: https://gitlab.cin.ufpe.br/vrs2/iot-trafficlight-final/-/blob/main/node_modules/event-target-shim/dist/event-target-shim.mjs?ref_type=heads#L40
When adding the Sentry console integration and also filtering by asserts, the above snippet can be called when we are symbolicating in dev builds, creating new events, that would then, be again symbolicated, and so on...
By avoiding the symbolication of events that comes from this specific assert, apps when tested in debug mode should no longer freeze when loading the console integration.
Fixes: #3992
Lastly. I marked it as no breaking changes since this only affect local builds
💚 How did you test it?
Tests, locally, replicated the problematic library code so it is easier to test it on the sample app.
📝 Checklist
sendDefaultPII
is enabled🔮 Next steps