Report unhandled errors from our extension
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user