Report unhandled errors from our extension

This commit is contained in:
Robert
2023-03-02 15:32:23 +00:00
parent 68ce7c3b53
commit 9386817727
2 changed files with 52 additions and 1 deletions

View File

@@ -2,6 +2,8 @@
## [UNRELEASED]
- Send telemetry about unhandled errors happening within the extension. [#2125](https://github.com/github/vscode-codeql/pull/2125)
## 1.7.11 - 1 March 2023
- Enable collection of telemetry concerning interactions with UI elements, including buttons, links, and other inputs. [#2114](https://github.com/github/vscode-codeql/pull/2114)

View File

@@ -72,7 +72,12 @@ import {
tmpDir,
tmpDirDisposal,
} from "./helpers";
import { asError, assertNever, getErrorMessage } from "./pure/helpers-pure";
import {
asError,
assertNever,
getErrorMessage,
getErrorStack,
} from "./pure/helpers-pure";
import { spawnIdeServer } from "./ide-server";
import { ResultsView } from "./interface";
import { WebviewReveal } from "./interface-utils";
@@ -235,6 +240,7 @@ export async function activate(
const distributionConfigListener = new DistributionConfigListener();
await initializeLogging(ctx);
await initializeTelemetry(extension, ctx);
addUnhandledRejectionListener();
install();
const codelensProvider = new QuickEvalCodeLensProvider();
@@ -1569,6 +1575,49 @@ async function activateWithInstalledDistribution(
};
}
function addUnhandledRejectionListener() {
const handler = (error: unknown) => {
// This listener will be triggered for errors from other extensions as
// well as errors from this extension. We don't want to flood the user
// with popups about errors from other extensions, and we don't want to
// report them in our telemetry.
//
// The stack trace gets redacted before being sent as telemetry, but at
// this point in the code we have the full unredacted information.
const isFromThisExtension =
extension && getErrorStack(error).includes(extension.extensionPath);
if (isFromThisExtension) {
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(
`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,