feat(node): App Not Responding with stack traces#9079
feat(node): App Not Responding with stack traces#9079AbhiPrasad merged 15 commits intogetsentry:developfrom
Conversation
| * Converted to a tag on ingest and used in various ways in the UI. | ||
| */ | ||
| handled: boolean; | ||
| handled?: boolean; |
There was a problem hiding this comment.
The android SDK submits ARN events without handled set, and neither true/false make sense here so I made this optional.
|
|
||
| const testScriptPath = path.resolve(__dirname, 'scenario.js'); | ||
|
|
||
| childProcess.exec(`node ${testScriptPath}`, { encoding: 'utf8' }, (_, stdout) => { |
Check warning
Code scanning / CodeQL
Shell command built from environment values
|
|
||
| const testScriptPath = path.resolve(__dirname, 'scenario.mjs'); | ||
|
|
||
| childProcess.exec(`node ${testScriptPath}`, { encoding: 'utf8' }, (_, stdout) => { |
Check warning
Code scanning / CodeQL
Shell command built from environment values
mydea
left a comment
There was a problem hiding this comment.
This is really cool! Great work 🎉
There was a problem hiding this comment.
The promise not resolving in the child process is so clever.
Can we add checks + docstrings for minimum node version?
Not going to merge in just yet, I'm going to bikeshed naming with the team on monday and then we can merge it in after final decision has been made there.
The CJS test is passing on the Node v10 integration tests and I can't see any reason why I wouldn't also work on v8 too. I only testing ESM on Node >= v14 since the test was failing for v12. When was top-level await supported from? |
Co-authored-by: Abhijeet Prasad <devabhiprasad@gmail.com>
|
Top level await is supported for Node 14+, so makes sense for me. Let's make it min required Node 10. |
|
One thing I think this PR doesn't yet cover well enough is handling of unexpected errors. For example if the child process fails to start, we probably want to just log that rather than stop the entire app from starting. |
…ascript into feat/node-anr # Conflicts: # packages/utils/src/anr.ts
This PR adds ANR detection for Node via a forked child process. The
child process runs the same entry point as the main app. To ensure that
the main app code does not run in the child process, we use a promise
that only resolves in the main process.
When the `captureStackTrace` option is enabled, debugging is enabled in
the main app process and the child process uses WebSockets to capture
stack traces via the v8 inspector API.
Overhead is expected to be minimal. With no ANR detected, the only
overhead in the main app process is polling the child process over IPC
by default every 50ms. The ANR child process consumes around 50-60 MB or
RAM and simply keeps track of the polling. Once ANR has been detected,
the main process will get paused briefly in the debugger to capture a
stack trace frames. At this point, the event loop has been blocked for
seconds so the debugging overhead can be considered negligible.
Once an ANR event has been reported, the child process exits to prevent
further duplicate events.
```ts
import { init, enableANRDetection } from '@sentry/node';
init({ dsn: "__DSN__" });
// ESM supports top-level await
await enableANRDetection({ captureStackTrace: true });
runApp();
// for CJS you'll need then
enableANRDetection({ captureStackTrace: true }).then(() => {
runApp();
})
```
Co-authored-by: Abhijeet Prasad <devabhiprasad@gmail.com>
This PR adds ANR detection for Node via a forked child process. The child process runs the same entry point as the main app. To ensure that the main app code does not run in the child process, we use a promise that only resolves in the main process.
When the
captureStackTraceoption is enabled, debugging is enabled in the main app process and the child process uses WebSockets to capture stack traces via the v8 inspector API.Overhead is expected to be minimal. With no ANR detected, the only overhead in the main app process is polling the child process over IPC by default every 50ms. The ANR child process consumes around 50-60 MB or RAM and simply keeps track of the polling. Once ANR has been detected, the main process will get paused briefly in the debugger to capture a stack trace frames. At this point, the event loop has been blocked for seconds so the debugging overhead can be considered negligible.
Once an ANR event has been reported, the child process exits to prevent further duplicate events.
It has the following options:
Here is an example event:
