FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

errors: improve hideStackFrames by Uzlopak · Pull Request #49990 · nodejs/node · GitHub

/ node Public

errors: improve hideStackFrames - #49990

Merged
nodejs-github-bot merged 1 commit into
nodejs:mainfrom
Uzlopak:hidestack-frames
Nov 11, 2023
Merged

errors: improve hideStackFrames#49990
nodejs-github-bot merged 1 commit into
nodejs:mainfrom
Uzlopak:hidestack-frames

Conversation

Uzlopak commented Oct 1, 2023
edited
Loading

Copy link
Copy Markdown
Contributor

This PR improves the hideStackFrames logic.

hideStackFrames is used to hide function calls from stracktraces of Errors. E.g. we call Buffer.alloc(size), then we check if the parameter size is an integer and call validateNumber(size, 'size', 0, kMaxLength);.

'use strict'

try {
    Buffer.alloc('1')
} catch (err) {
    console.error(err.stack)
}

then we get the following stacktrace:

TypeError [ERR_INVALID_ARG_TYPE]: The "size" argument must be of type number. Received type string ('1')
    at Function.alloc (node:buffer:393:3)
    at Object.<anonymous> (/home/aras/workspace/node/test.js:4:12)
    at Module._compile (node:internal/modules/cjs/loader:1369:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
    at Module.load (node:internal/modules/cjs/loader:1201:32)
    at Module._load (node:internal/modules/cjs/loader:1017:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:104:12)
    at node:internal/main/run_main_module:23:47

If we remove the hideStackFrame wrapping for demonstration purposes we get:

TypeError [ERR_INVALID_ARG_TYPE]: The "size" argument must be of type number. Received type string ('1')
    at validateNumber (node:internal/validators:177:11)
    at Function.alloc (node:buffer:393:3)
    at Object.<anonymous> (/home/aras/workspace/node/test.js:4:12)
    at Module._compile (node:internal/modules/cjs/loader:1369:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
    at Module.load (node:internal/modules/cjs/loader:1201:32)
    at Module._load (node:internal/modules/cjs/loader:1017:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:104:12)
    at node:internal/main/run_main_module:23:47

So we have the additional at validateNumber (node:internal/validators:177:11) entry.

We want to hide this frame, as it is some node internal information, and does not give any benefit for the developer.

Javascript has no inline specifier, so we have to hide it differently. In main branch this is solved by prefixing the function name with __node_internal_ and then generating the whole stacktrace with captureLargerStackTrace, which sets Error.stackTraceLimit = Infinity. When we then call Error.stack, prepareStackTrace will filter out the all frames, which start with __node_internal_.

But we dont need the whole stackTrace. We only need a limited number, by default 10 frames.

To achieve this we just generate the necessary stackTrace.

So hideStackFrames will wrap the original function and will capture the correct stack trace if an error is thrown. Functions which are wrapped have to call the HideStackFramesError Errors and wont have a Stack trace.

An edge case is when a function, which uses hideStackFrames calls another function which is wrapped with hideStackFrames. To avoid double generation of the stack, a function which is wrapped with hideStackFrames exposes a function as attribute of the wrapped function called .withoutStackTrace. The outer function will then get the necessary stack trace.

Usually double wrapped functions are validators. I would have liked to extract them all into validators.js or into module/validators.js. But this would have reduced the readability further.

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/http
  • @nodejs/http2
  • @nodejs/net

nodejs-github-bot added lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels Oct 1, 2023

mcollina commented Oct 1, 2023

Copy link
Copy Markdown
Member

what's the benefit/performance diff?

Uzlopak commented Oct 1, 2023

Copy link
Copy Markdown
Contributor Author

My benchmarks dont show regressions.
But if we go on, I would ensure that all touched code does not contain any perf regressions.

The benefit is, that the stack trace will be generated propery, without the need to call captureLargerStackTrace. So we wont be forced to keep infinity amount of CallSites just to kick some.

On the long run, i want to try to remove prepareStackTrace.

Currently i investigate what this overrideStackTrace Map is doing, and how we can avoid it.

Comment thread lib/internal/errors.js Outdated

benjamingr Oct 1, 2023
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Won't this mess with the .name of the error and how stack traces look (vs the previous implementation)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

The only reason i created this class, was because to avoid to patch everywhere the logic for Error.stackTraceLimit over and over.

The name should be the same imho. But i can tackle it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Thanks let me know when ready

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Uzlopak commented Oct 2, 2023

Copy link
Copy Markdown
Contributor Author

The existing tests pass.

Next step is to remove the captureLargerStackTrace function and ensure that the logic is equivalent.

Imho this is an exciting PR for me. If done right, this should improve the performance of basically every error case. And tbh it seems to be a smart solution (patting on my own shoulder).

Also it will cover all the validateX functions.so it should expose less unnecessary stacks.

Uzlopak commented Oct 2, 2023

Copy link
Copy Markdown
Contributor Author

Uzlopak force-pushed the hidestack-frames branch 4 times, most recently from a2134fc to 3f94be4 Compare October 4, 2023 20:11

Uzlopak commented Oct 4, 2023

Copy link
Copy Markdown
Contributor Author

@anonrig can you please add the author-ready tag?

I would like to discuss this.

anonrig commented Oct 4, 2023

Copy link
Copy Markdown
Member

@anonrig can you please add the author-ready tag?

author-ready requires at least 1 collaborator approval. I don't have enough knowledge to review this. I recommend @benjamingr or @mcollina to leave a review before adding author-ready

anonrig added the request-ci Add this label to start a Jenkins CI on a PR. label Oct 4, 2023
anonrig requested review from benjamingr and mcollina October 4, 2023 20:24
github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Oct 4, 2023

Copy link
Copy Markdown
Collaborator

tniessen added the review wanted PRs that need reviews. label Oct 4, 2023

targos commented Oct 5, 2023

Copy link
Copy Markdown
Member

Also @BridgeAR

Uzlopak force-pushed the hidestack-frames branch 3 times, most recently from da8ff55 to 134ea2b Compare October 5, 2023 12:05

mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

lgtm

Comment thread lib/internal/errors.js Outdated

Copy link
Copy Markdown
Member

You are correct

Comment thread lib/internal/errors.js
});
if (otherClasses.includes(HideStackFramesError)) {
if (otherClasses.length !== 1) {
otherClasses.forEach((clazz) => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@mcollina
@anonrig

Should we use a for loop instead?

Comment thread lib/internal/errors.js
otherClasses.forEach((clazz) => {
def[clazz.name] = makeNodeErrorWithCode(clazz, sym);
});
if (otherClasses.includes(HideStackFramesError)) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@mcollina
@anonrig

Should we use primordials?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I would recommend we do.

Uzlopak commented Oct 14, 2023

Copy link
Copy Markdown
Contributor Author

@benjamingr
Can you have a look?

benjamingr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Don't have capacity, sorry, unblocking so others can progress

benjamingr dismissed their stale review October 14, 2023 20:33

unavailable

Uzlopak requested review from Qard and RafaelGSS October 14, 2023 20:35

Uzlopak commented Oct 15, 2023
edited
Loading

Copy link
Copy Markdown
Contributor Author

@anonrig
Can you now add the author-ready tag, please?

anonrig added author ready PRs that have at least one approval, no outstanding review comments, and a CI started. request-ci Add this label to start a Jenkins CI on a PR. labels Oct 15, 2023
github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Oct 15, 2023

Copy link
Copy Markdown
Collaborator

Uzlopak commented Oct 15, 2023

Copy link
Copy Markdown
Contributor Author

@anonrig
can you retrigger the failed CI,please?

Copy link
Copy Markdown
Collaborator

Copy link
Copy Markdown
Collaborator

nodejs-github-bot commented Nov 2, 2023
edited by jasnell
Loading

Copy link
Copy Markdown
Collaborator

mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

lgtm

jasnell added the commit-queue Add this label to land a pull request using GitHub Actions. label Nov 11, 2023
nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Nov 11, 2023
nodejs-github-bot merged commit 83e6350 into nodejs:main Nov 11, 2023

Copy link
Copy Markdown
Collaborator

Landed in 83e6350

targos pushed a commit that referenced this pull request Nov 11, 2023
PR-URL: #49990
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Uzlopak deleted the hidestack-frames branch November 13, 2023 07:42
targos pushed a commit that referenced this pull request Nov 14, 2023
PR-URL: #49990
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
richardlau pushed a commit that referenced this pull request Mar 25, 2024
PR-URL: #49990
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
richardlau mentioned this pull request Mar 25, 2024
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author ready PRs that have at least one approval, no outstanding review comments, and a CI started. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. needs-citgm PRs that need a CITGM CI run. review wanted PRs that need reviews.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants


Back | FazBrowse Home | New Git URL