Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions extensions/ql-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ export async function activate(
const distributionConfigListener = new DistributionConfigListener();
await initializeLogging(ctx);
await initializeTelemetry(extension, ctx);
addUnhandledRejectionListener();
install();

const codelensProvider = new QuickEvalCodeLensProvider();
Expand Down Expand Up @@ -1529,6 +1530,35 @@ async function activateWithInstalledDistribution(
};
}

function addUnhandledRejectionListener() {
const handler = (error: unknown) => {
const message = redactableError(
asError(error),
)`Unhandled error: ${getErrorMessage(error)}`;
// Add a catch so that showAndLogExceptionWithTelemetry fails, we avoid
// 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.

`Failed to send error telemetry: ${getErrorMessage(telemetryError)}`,
);
void extLogger.log(message.fullMessage);
},
);
};

// "uncaughtException" will trigger whenever an exception reaches the top level.
// This covers extension initialization and any code within a `setTimeout`.
// Notably this does not include exceptions thrown when executing commands,
// because `commandRunner` wraps the command body and handles errors.
process.addListener("uncaughtException", handler);

// "unhandledRejection" will trigger whenever any promise is rejected and it is
// not handled by a "catch" somewhere in the promise chain. This includes when
// a promise is used with the "void" operator.
process.addListener("unhandledRejection", handler);
}

async function createQueryServer(
qlConfigurationListener: QueryServerConfigListener,
cliServer: CodeQLCliServer,
Expand Down