Skip to content

Add unhandled rejection listener#2076

Merged
robertbrignull merged 1 commit intomainfrom
robertbrignull/unhandled_rejection
Feb 15, 2023
Merged

Add unhandled rejection listener#2076
robertbrignull merged 1 commit intomainfrom
robertbrignull/unhandled_rejection

Conversation

@robertbrignull
Copy link
Copy Markdown
Contributor

@robertbrignull robertbrignull commented Feb 14, 2023

Adds listeners for unhandled exceptions or rejected promises. The intention here is to emit telemetry for them so that we know how frequently this is happening for users.

There is some general advice online that one should not just catch unhandled exceptions and try to carry on regardless. I think this PR isn't making that behaviour any more unsafe because that's already how VS Code behaves for exceptions in extension code. We already aren't crashing the whole NodeJS process, so I think by adding this handler to logs telemetry we aren't changing the overall program behaviour.

Checklist

  • CHANGELOG.md has been updated to incorporate all user visible changes made by this pull request.
    • Not necessary because telemetry logging is disabled by default.
  • Issues have been created for any UI or other user-facing changes made by this pull request.
  • [Maintainers only] If this pull request makes user-facing changes that require documentation changes, open a corresponding docs pull request in the github/codeql repo and add the ready-for-doc-review label there.

Comment on lines +1535 to +1547
void showAndLogExceptionWithTelemetry(
redactableError(asError(error))`Unhandled error: ${getErrorMessage(
error,
)}`,
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What happens if showAndLogExceptionWithTelemetry throws? It will be an unhandledRejection, I think. And this would cause a loop of this handler being called. Unlikely to happen, but if it happens, it will be bad.

I think it would be best to add a .then(...) handler here, with a catch argument that just logs to. Or, you can just be really sure that showAndLogExceptionWithTelemetry will never throw.

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.

Good point. I think we can add a catch to showAndLogExceptionWithTelemetry which then logs in a much more simple way. Or alternatively we could just fully ignore it in this case. That wouldn't put us in a worse place than we were before this PR.

@robertbrignull robertbrignull force-pushed the robertbrignull/unhandled_rejection branch from 60532e1 to 5e5834e Compare February 15, 2023 14:13
@robertbrignull robertbrignull marked this pull request as ready for review February 15, 2023 14:16
@robertbrignull robertbrignull requested a review from a team as a code owner February 15, 2023 14:16
@robertbrignull robertbrignull requested a review from a team February 15, 2023 14:16
@robertbrignull robertbrignull force-pushed the robertbrignull/unhandled_rejection branch from 5e5834e to 2ebfea1 Compare February 15, 2023 14:28
// triggering "unhandledRejection" and avoid an infinite loop
showAndLogExceptionWithTelemetry(message).catch(
(telemetryError: unknown) => {
void extLogger.log(
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.

To test this I tried throwing a test exception, and also added an error to showAndLogExceptionWithTelemetry. Annoying something weird is going on and the second error seems to be getting lost. For example it prints

Failed to send error telemetry: Cannot read properties of undefined (reading 't')
Unhandled error: Cannot read properties of undefined (reading 't')

even though the two messages should be different.

I'm therefore not sure whether to keep this or just log one of the messages.

Copy link
Copy Markdown
Contributor

@aeisenberg aeisenberg left a comment

Choose a reason for hiding this comment

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

Nice

@robertbrignull
Copy link
Copy Markdown
Contributor Author

I've done some more manual testing of having or not having the rejection handler and throwing exceptions in various ways. I think it's all working as expected and won't cause problems. Also no telemetry is sent unless the config option is enabled, and that option is still currently off by default.

It does slightly change behaviour because some exceptions were previously lost and not shown to the user. If an exception happens in a command then it'll be shown to the user as an error, with the command name. If an exception happens within something like a setTimeout or an unhandled promise then it is not tied to the command in the same way and also not shown to the user.

I think this change of behaviour is acceptable. The existing logging is done by us, so our intention is to log exceptions. Therefore this PR makes the situation more consistent because now we're logging more exceptions that previously were lost.

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.

2 participants