Skip to content

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

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

lucas-zimerman
Copy link
Collaborator

@lucas-zimerman lucas-zimerman commented Apr 22, 2025

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 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

/**
 * Get private data.
 * @param {Event} event The event object to get private data.
 * @returns {PrivateData} The private data of the event.
 * @private
 */
function pd(event) {
    const retv = privateData.get(event);
    console.assert(
        retv != null,
        "'this' is expected an Event object, but got",
        event
    );
    return retv
}

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

  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing
  • No breaking changes

🔮 Next steps

@lucas-zimerman lucas-zimerman marked this pull request as ready for review April 22, 2025 21:49
@lucas-zimerman lucas-zimerman changed the title Fix: don't symbolicate console asserts that came from metro. Fix: don't symbolicate console asserts that comes from metro. Apr 22, 2025
Copy link
Contributor

github-actions bot commented Apr 22, 2025

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 395.92 ms 405.82 ms 9.90 ms
Size 17.75 MiB 20.13 MiB 2.38 MiB

Baseline results on branch: main

Startup times

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

Previous results on branch: lz/fix-console

Startup times

Revision Plain With Sentry Diff
4fd28cc 428.30 ms 443.88 ms 15.58 ms
63aead8 427.73 ms 422.74 ms -4.98 ms

App size

Revision Plain With Sentry Diff
4fd28cc 17.75 MiB 20.13 MiB 2.38 MiB
63aead8 17.75 MiB 20.13 MiB 2.38 MiB

Copy link
Contributor

github-actions bot commented Apr 22, 2025

iOS (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1219.22 ms 1219.24 ms 0.02 ms
Size 2.63 MiB 3.79 MiB 1.16 MiB

Baseline results on branch: main

Startup times

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

Copy link
Contributor

github-actions bot commented Apr 22, 2025

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 391.38 ms 401.92 ms 10.54 ms
Size 7.15 MiB 8.40 MiB 1.25 MiB

Baseline results on branch: main

Startup times

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

Previous results on branch: lz/fix-console

Startup times

Revision Plain With Sentry Diff
4fd28cc+dirty 382.06 ms 403.94 ms 21.88 ms
63aead8+dirty 391.72 ms 411.84 ms 20.12 ms

App size

Revision Plain With Sentry Diff
4fd28cc+dirty 7.15 MiB 8.40 MiB 1.25 MiB
63aead8+dirty 7.15 MiB 8.40 MiB 1.25 MiB

Copy link
Contributor

github-actions bot commented Apr 22, 2025

iOS (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1233.94 ms 1231.29 ms -2.65 ms
Size 3.19 MiB 4.36 MiB 1.17 MiB

Baseline results on branch: main

Startup times

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

Copy link
Collaborator

@antonis antonis left a 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.

@krystofwoldrich
Copy link
Member

The code looks good, do you have an example stack how the problematic assert gets called?

Is it inside of the symbolicateStackTrace call?
It would be useful to document the stack for the future.

@lucas-zimerman
Copy link
Collaborator Author

lucas-zimerman commented Apr 23, 2025

The code looks good, do you have an example stack how the problematic assert gets called?

Is it inside of the symbolicateStackTrace call? It would be useful to document the stack for the future.

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 symbolicateStackTrace

Do you have any preference on where I could store this stack trace?

@krystofwoldrich
Copy link
Member

krystofwoldrich commented Apr 24, 2025

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.

https://github.com/facebook/react-native/blob/f0527d86623112eee1e80da7884081f7ecf59bea/packages/react-native/Libraries/Network/XMLHttpRequest.js#L535

at pd 
at setPassiveListener 
at dispatchEvent 
at setReadyState
at open
at Promise
at fetch

@krystofwoldrich
Copy link
Member

Looking at the cause the best solution would be to use a network request which calls console.* inside of the consoleSandbox (https://github.com/getsentry/sentry-javascript/blob/bf323b111b7e7b781e60e6299e432ce89f144970/packages/core/src/utils-hoist/logger.ts#L40). That way we would avoid the regression when the error message changes or a different console.assert/error is called.

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.

https://github.com/facebook/react-native/blob/f0527d86623112eee1e80da7884081f7ecf59bea/packages/react-native/Libraries/Network/XMLHttpRequest.js#L97

Let me know what do you think about that?

@lucas-zimerman
Copy link
Collaborator Author

image
here is the next commit but without the console sandbox callback

@lucas-zimerman
Copy link
Collaborator Author

Looking at the cause the best solution would be to use a network request which calls console.* inside of the consoleSandbox (https://github.com/getsentry/sentry-javascript/blob/bf323b111b7e7b781e60e6299e432ce89f144970/packages/core/src/utils-hoist/logger.ts#L40). That way we would avoid the regression when the error message changes or a different console.assert/error is called.

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.

https://github.com/facebook/react-native/blob/f0527d86623112eee1e80da7884081f7ecf59bea/packages/react-native/Libraries/Network/XMLHttpRequest.js#L97

Let me know what do you think about that?

That surely works better , I have applied your suggestion on cb9ef09

Comment on lines +857 to +863
(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);
});
Copy link
Member

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.

Copy link
Collaborator Author

@lucas-zimerman lucas-zimerman Apr 28, 2025

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

Copy link
Member

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.

Copy link
Member

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.

Copy link
Collaborator

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 👍

Copy link
Collaborator Author

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

@lucas-zimerman lucas-zimerman marked this pull request as draft May 5, 2025 19: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.

App performance greatly reduced by captureConsoleIntegration
3 participants