Change showAndLog functions to take NotificationLogger
This commit is contained in:
@@ -160,6 +160,7 @@ export class DistributionManager implements DistributionProvider {
|
||||
if (this.config.customCodeQlPath) {
|
||||
if (!(await pathExists(this.config.customCodeQlPath))) {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`The CodeQL executable path is specified as "${this.config.customCodeQlPath}" ` +
|
||||
"by a configuration setting, but a CodeQL executable could not be found at that path. Please check " +
|
||||
"that a CodeQL executable exists at the specified path or remove the setting.",
|
||||
@@ -852,6 +853,7 @@ export async function getExecutableFromDirectory(
|
||||
|
||||
function warnDeprecatedLauncher() {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`The "${deprecatedCodeQlLauncherName()!}" launcher has been deprecated and will be removed in a future version. ` +
|
||||
`Please use "${codeQlLauncherName()}" instead. It is recommended to update to the latest CodeQL binaries.`,
|
||||
);
|
||||
|
||||
@@ -59,6 +59,7 @@ export async function askForLanguage(
|
||||
throw new UserCancellationException("Cancelled.");
|
||||
} else {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
"Language not found. Language must be specified manually.",
|
||||
);
|
||||
}
|
||||
@@ -67,6 +68,7 @@ export async function askForLanguage(
|
||||
|
||||
if (!isQueryLanguage(language)) {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Language '${language}' is not supported. Only languages ${Object.values(
|
||||
QueryLanguage,
|
||||
).join(", ")} are supported.`,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from "./logger";
|
||||
export * from "./notification-logger";
|
||||
export * from "./tee-logger";
|
||||
export * from "./vscode/loggers";
|
||||
export * from "./vscode/output-channel-logger";
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { Logger } from "./logger";
|
||||
|
||||
export interface NotificationLogger extends Logger {
|
||||
showErrorMessage(message: string): Promise<void>;
|
||||
showWarningMessage(message: string): Promise<void>;
|
||||
showInformationMessage(message: string): Promise<void>;
|
||||
}
|
||||
@@ -1,11 +1,15 @@
|
||||
import { window as Window, OutputChannel, Progress } from "vscode";
|
||||
import { Logger, LogOptions } from "../logger";
|
||||
import { DisposableObject } from "../../../pure/disposable-object";
|
||||
import { NotificationLogger } from "../notification-logger";
|
||||
|
||||
/**
|
||||
* A logger that writes messages to an output channel in the VS Code Output tab.
|
||||
*/
|
||||
export class OutputChannelLogger extends DisposableObject implements Logger {
|
||||
export class OutputChannelLogger
|
||||
extends DisposableObject
|
||||
implements Logger, NotificationLogger
|
||||
{
|
||||
public readonly outputChannel: OutputChannel;
|
||||
isCustomLogDirectory: boolean;
|
||||
|
||||
@@ -42,6 +46,30 @@ export class OutputChannelLogger extends DisposableObject implements Logger {
|
||||
show(preserveFocus?: boolean): void {
|
||||
this.outputChannel.show(preserveFocus);
|
||||
}
|
||||
|
||||
async showErrorMessage(message: string): Promise<void> {
|
||||
await this.showMessage(message, Window.showErrorMessage);
|
||||
}
|
||||
|
||||
async showInformationMessage(message: string): Promise<void> {
|
||||
await this.showMessage(message, Window.showInformationMessage);
|
||||
}
|
||||
|
||||
async showWarningMessage(message: string): Promise<void> {
|
||||
await this.showMessage(message, Window.showWarningMessage);
|
||||
}
|
||||
|
||||
private async showMessage(
|
||||
message: string,
|
||||
show: (message: string, ...items: string[]) => Thenable<string | undefined>,
|
||||
): Promise<void> {
|
||||
const label = "Show Log";
|
||||
const result = await show(message, label);
|
||||
|
||||
if (result === label) {
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type ProgressReporter = Progress<{ message: string }>;
|
||||
|
||||
@@ -54,9 +54,7 @@ export function registerCommandWithErrorHandling(
|
||||
if (e.silent) {
|
||||
void outputLogger.log(errorMessage.fullMessage);
|
||||
} else {
|
||||
void showAndLogWarningMessage(errorMessage.fullMessage, {
|
||||
outputLogger,
|
||||
});
|
||||
void showAndLogWarningMessage(outputLogger, errorMessage.fullMessage);
|
||||
}
|
||||
} else {
|
||||
// Include the full stack in the error log only.
|
||||
@@ -64,8 +62,7 @@ export function registerCommandWithErrorHandling(
|
||||
const fullMessage = errorStack
|
||||
? `${errorMessage.fullMessage}\n${errorStack}`
|
||||
: errorMessage.fullMessage;
|
||||
void showAndLogExceptionWithTelemetry(errorMessage, {
|
||||
outputLogger,
|
||||
void showAndLogExceptionWithTelemetry(outputLogger, errorMessage, {
|
||||
fullMessage,
|
||||
extraTelemetryProperties: {
|
||||
command: commandId,
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
getErrorStack,
|
||||
} from "../../pure/helpers-pure";
|
||||
import { showAndLogExceptionWithTelemetry } from "./log";
|
||||
import { extLogger } from "../logging";
|
||||
|
||||
export async function tryOpenExternalFile(
|
||||
commandManager: AppCommandManager,
|
||||
@@ -34,6 +35,7 @@ the file in the file explorer and dragging it into the workspace.`,
|
||||
await commandManager.execute("revealFileInOS", uri);
|
||||
} catch (e) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(e),
|
||||
)`Failed to reveal file in OS: ${getErrorMessage(e)}`,
|
||||
@@ -42,6 +44,7 @@ the file in the file explorer and dragging it into the workspace.`,
|
||||
}
|
||||
} else {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(asError(e))`Could not open file ${fileLocation}`,
|
||||
{
|
||||
fullMessage: `${getErrorMessage(e)}\n${getErrorStack(e)}`,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { window } from "vscode";
|
||||
import { RedactableError } from "../../pure/errors";
|
||||
import { telemetryListener } from "../../telemetry";
|
||||
import { extLogger, OutputChannelLogger } from "../logging";
|
||||
import { NotificationLogger } from "../logging";
|
||||
|
||||
interface ShowAndLogExceptionOptions extends ShowAndLogOptions {
|
||||
/** Custom properties to include in the telemetry report. */
|
||||
@@ -9,10 +8,6 @@ interface ShowAndLogExceptionOptions extends ShowAndLogOptions {
|
||||
}
|
||||
|
||||
interface ShowAndLogOptions {
|
||||
/** The output logger that will receive the message. */
|
||||
outputLogger?: OutputChannelLogger;
|
||||
/** A set of items that will be rendered as actions in the message. */
|
||||
items?: string[];
|
||||
/**
|
||||
* An alternate message that is added to the log, but not displayed in the popup.
|
||||
* This is useful for adding extra detail to the logs that would be too noisy for the popup.
|
||||
@@ -23,34 +18,39 @@ interface ShowAndLogOptions {
|
||||
/**
|
||||
* Show an error message, log it to the console, and emit redacted information as telemetry
|
||||
*
|
||||
* @param logger The logger that will receive the message.
|
||||
* @param error The error to show. Only redacted information will be included in the telemetry.
|
||||
* @param options See individual fields on `ShowAndLogExceptionOptions` type.
|
||||
*
|
||||
* @return A promise that resolves to the selected item or undefined when being dismissed.
|
||||
*/
|
||||
export async function showAndLogExceptionWithTelemetry(
|
||||
logger: NotificationLogger,
|
||||
error: RedactableError,
|
||||
options: ShowAndLogExceptionOptions = {},
|
||||
): Promise<string | undefined> {
|
||||
): Promise<void> {
|
||||
telemetryListener?.sendError(error, options.extraTelemetryProperties);
|
||||
return showAndLogErrorMessage(error.fullMessage, options);
|
||||
return showAndLogErrorMessage(logger, error.fullMessage, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an error message and log it to the console
|
||||
*
|
||||
* @param logger The logger that will receive the message.
|
||||
* @param message The message to show.
|
||||
* @param options See individual fields on `ShowAndLogOptions` type.
|
||||
* @param options? See individual fields on `ShowAndLogOptions` type.
|
||||
*
|
||||
* @return A promise that resolves to the selected item or undefined when being dismissed.
|
||||
*/
|
||||
export async function showAndLogErrorMessage(
|
||||
logger: NotificationLogger,
|
||||
message: string,
|
||||
options?: ShowAndLogOptions,
|
||||
): Promise<string | undefined> {
|
||||
): Promise<void> {
|
||||
return internalShowAndLog(
|
||||
logger,
|
||||
dropLinesExceptInitial(message),
|
||||
window.showErrorMessage,
|
||||
logger.showErrorMessage,
|
||||
{ fullMessage: message, ...options },
|
||||
);
|
||||
}
|
||||
@@ -62,48 +62,53 @@ function dropLinesExceptInitial(message: string, n = 2) {
|
||||
/**
|
||||
* Show a warning message and log it to the console
|
||||
*
|
||||
* @param logger The logger that will receive the message.
|
||||
* @param message The message to show.
|
||||
* @param options See individual fields on `ShowAndLogOptions` type.
|
||||
* @param options? See individual fields on `ShowAndLogOptions` type.
|
||||
*
|
||||
* @return A promise that resolves to the selected item or undefined when being dismissed.
|
||||
*/
|
||||
export async function showAndLogWarningMessage(
|
||||
logger: NotificationLogger,
|
||||
message: string,
|
||||
options?: ShowAndLogOptions,
|
||||
): Promise<string | undefined> {
|
||||
return internalShowAndLog(message, window.showWarningMessage, options);
|
||||
): Promise<void> {
|
||||
return internalShowAndLog(
|
||||
logger,
|
||||
message,
|
||||
logger.showWarningMessage,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an information message and log it to the console
|
||||
*
|
||||
* @param logger The logger that will receive the message.
|
||||
* @param message The message to show.
|
||||
* @param options See individual fields on `ShowAndLogOptions` type.
|
||||
* @param options? See individual fields on `ShowAndLogOptions` type.
|
||||
*
|
||||
* @return A promise that resolves to the selected item or undefined when being dismissed.
|
||||
*/
|
||||
export async function showAndLogInformationMessage(
|
||||
logger: NotificationLogger,
|
||||
message: string,
|
||||
options?: ShowAndLogOptions,
|
||||
): Promise<string | undefined> {
|
||||
return internalShowAndLog(message, window.showInformationMessage, options);
|
||||
): Promise<void> {
|
||||
return internalShowAndLog(
|
||||
logger,
|
||||
message,
|
||||
logger.showInformationMessage,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
type ShowMessageFn = (
|
||||
message: string,
|
||||
...items: string[]
|
||||
) => Thenable<string | undefined>;
|
||||
|
||||
async function internalShowAndLog(
|
||||
logger: NotificationLogger,
|
||||
message: string,
|
||||
fn: ShowMessageFn,
|
||||
{ items = [], outputLogger = extLogger, fullMessage }: ShowAndLogOptions = {},
|
||||
): Promise<string | undefined> {
|
||||
const label = "Show Log";
|
||||
void outputLogger.log(fullMessage || message);
|
||||
const result = await fn(message, label, ...items);
|
||||
if (result === label) {
|
||||
outputLogger.show();
|
||||
}
|
||||
return result;
|
||||
fn: (message: string) => Promise<void>,
|
||||
{ fullMessage }: ShowAndLogOptions = {},
|
||||
): Promise<void> {
|
||||
void logger.log(fullMessage || message);
|
||||
await fn.bind(logger)(message);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
TreeViewContextSingleSelectionCommandFunction,
|
||||
} from "../commands";
|
||||
import { showAndLogErrorMessage } from "./log";
|
||||
import { extLogger } from "../logging";
|
||||
|
||||
// A hack to match types that are not an array, which is useful to help avoid
|
||||
// misusing createSingleSelectionCommand, e.g. where T accidentally gets instantiated
|
||||
@@ -32,7 +33,10 @@ export function createSingleSelectionCommand<T extends NotArray>(
|
||||
if (multiSelect === undefined || multiSelect.length === 1) {
|
||||
return f(singleItem);
|
||||
} else {
|
||||
void showAndLogErrorMessage(`Please select a single ${itemName}.`);
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Please select a single ${itemName}.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
ToCompareViewMessage,
|
||||
QueryCompareResult,
|
||||
} from "../pure/interface-types";
|
||||
import { Logger } from "../common";
|
||||
import { extLogger, Logger } from "../common";
|
||||
import { CodeQLCliServer } from "../codeql-cli/cli";
|
||||
import { DatabaseManager } from "../databases/local-databases";
|
||||
import { jumpToLocation } from "../databases/local-databases/locations";
|
||||
@@ -152,6 +152,7 @@ export class CompareView extends AbstractWebview<
|
||||
|
||||
case "unhandledError":
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
msg.error,
|
||||
)`Unhandled error in result comparison view: ${msg.error.message}`,
|
||||
|
||||
@@ -10,6 +10,7 @@ import { App } from "../common/app";
|
||||
import { withProgress } from "../common/vscode/progress";
|
||||
import { pickExtensionPackModelFile } from "./extension-pack-picker";
|
||||
import { showAndLogErrorMessage } from "../common/vscode/log";
|
||||
import { extLogger } from "../common";
|
||||
|
||||
const SUPPORTED_LANGUAGES: string[] = ["java", "csharp"];
|
||||
|
||||
@@ -56,12 +57,13 @@ export class DataExtensionsEditorModule {
|
||||
"codeQL.openDataExtensionsEditor": async () => {
|
||||
const db = this.databaseManager.currentDatabaseItem;
|
||||
if (!db) {
|
||||
void showAndLogErrorMessage("No database selected");
|
||||
void showAndLogErrorMessage(extLogger, "No database selected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SUPPORTED_LANGUAGES.includes(db.language)) {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`The data extensions editor is not supported for ${db.language} databases.`,
|
||||
);
|
||||
return;
|
||||
@@ -71,6 +73,7 @@ export class DataExtensionsEditorModule {
|
||||
async (progress, token) => {
|
||||
if (!(await this.cliServer.cliConstraints.supportsQlpacksKind())) {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`This feature requires CodeQL CLI version ${CliVersionConstraint.CLI_VERSION_WITH_QLPACKS_KIND.format()} or later.`,
|
||||
);
|
||||
return;
|
||||
|
||||
@@ -208,6 +208,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
|
||||
|
||||
if (!existingModeledMethods) {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Failed to parse data extension YAML ${this.modelFile.filename}.`,
|
||||
);
|
||||
return;
|
||||
@@ -219,6 +220,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Unable to read data extension YAML ${
|
||||
this.modelFile.filename
|
||||
}: ${getErrorMessage(e)}`,
|
||||
@@ -276,6 +278,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
|
||||
await this.clearProgress();
|
||||
} catch (err) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(err),
|
||||
)`Failed to load external API usages: ${getErrorMessage(err)}`,
|
||||
@@ -341,6 +344,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(e),
|
||||
)`Failed to generate flow model: ${getErrorMessage(e)}`,
|
||||
@@ -474,6 +478,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
|
||||
|
||||
if (e instanceof RequestError && e.status === 429) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(e)`Rate limit hit, please try again soon.`,
|
||||
);
|
||||
return null;
|
||||
|
||||
@@ -15,6 +15,7 @@ import { getErrorMessage } from "../pure/helpers-pure";
|
||||
import { ExtensionPack, ExtensionPackModelFile } from "./shared/extension-pack";
|
||||
import { showAndLogErrorMessage } from "../common/vscode/log";
|
||||
import { containsPath } from "../pure/files";
|
||||
import { extLogger } from "../common";
|
||||
|
||||
const maxStep = 3;
|
||||
|
||||
@@ -85,6 +86,7 @@ async function pickExtensionPack(
|
||||
Object.entries(extensionPacksInfo).map(async ([name, paths]) => {
|
||||
if (paths.length !== 1) {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Extension pack ${name} resolves to multiple paths`,
|
||||
{
|
||||
fullMessage: `Extension pack ${name} resolves to multiple paths: ${paths.join(
|
||||
@@ -102,11 +104,15 @@ async function pickExtensionPack(
|
||||
try {
|
||||
extensionPack = await readExtensionPack(path);
|
||||
} catch (e: unknown) {
|
||||
void showAndLogErrorMessage(`Could not read extension pack ${name}`, {
|
||||
fullMessage: `Could not read extension pack ${name} at ${path}: ${getErrorMessage(
|
||||
e,
|
||||
)}`,
|
||||
});
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Could not read extension pack ${name}`,
|
||||
{
|
||||
fullMessage: `Could not read extension pack ${name} at ${path}: ${getErrorMessage(
|
||||
e,
|
||||
)}`,
|
||||
},
|
||||
);
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { dir } from "tmp-promise";
|
||||
import { writeFile } from "fs-extra";
|
||||
import { dump as dumpYaml } from "js-yaml";
|
||||
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
|
||||
import { TeeLogger } from "../common";
|
||||
import { extLogger, TeeLogger } from "../common";
|
||||
import { isQueryLanguage } from "../common/query-language";
|
||||
import { CancellationToken } from "vscode";
|
||||
import { CodeQLCliServer } from "../codeql-cli/cli";
|
||||
@@ -41,6 +41,7 @@ export async function runQuery({
|
||||
|
||||
if (!isQueryLanguage(databaseItem.language)) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`Unsupported database language ${databaseItem.language}`,
|
||||
);
|
||||
return;
|
||||
@@ -49,6 +50,7 @@ export async function runQuery({
|
||||
const query = fetchExternalApiQueries[databaseItem.language];
|
||||
if (!query) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`No external API usage query found for language ${databaseItem.language}`,
|
||||
);
|
||||
return;
|
||||
@@ -104,6 +106,7 @@ export async function runQuery({
|
||||
|
||||
if (completedQuery.resultType !== QueryResultType.SUCCESS) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`External API usage query failed: ${
|
||||
completedQuery.message ?? "No message"
|
||||
}`,
|
||||
@@ -126,6 +129,7 @@ export async function readQueryResults({
|
||||
const bqrsInfo = await cliServer.bqrsInfo(bqrsPath);
|
||||
if (bqrsInfo["result-sets"].length !== 1) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`Expected exactly one result set, got ${bqrsInfo["result-sets"].length}`,
|
||||
);
|
||||
return undefined;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { DatabaseItem } from "../databases/local-databases";
|
||||
import { basename } from "path";
|
||||
import { QueryRunner } from "../query-server";
|
||||
import { CodeQLCliServer } from "../codeql-cli/cli";
|
||||
import { TeeLogger } from "../common";
|
||||
import { extLogger, TeeLogger } from "../common";
|
||||
import { extensiblePredicateDefinitions } from "./predicates";
|
||||
import { ProgressCallback } from "../common/vscode/progress";
|
||||
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
|
||||
@@ -81,6 +81,7 @@ async function getModeledMethodsFromFlow(
|
||||
): Promise<ModeledMethodWithSignature[]> {
|
||||
if (queryPath === undefined) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`Failed to find ${type} query`,
|
||||
);
|
||||
return [];
|
||||
@@ -115,6 +116,7 @@ async function getModeledMethodsFromFlow(
|
||||
);
|
||||
if (queryResult.resultType !== QueryResultType.SUCCESS) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`Failed to run ${basename(queryPath)} query: ${
|
||||
queryResult.message ?? "No message"
|
||||
}`,
|
||||
@@ -127,6 +129,7 @@ async function getModeledMethodsFromFlow(
|
||||
const bqrsInfo = await cliServer.bqrsInfo(bqrsPath);
|
||||
if (bqrsInfo["result-sets"].length !== 1) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`Expected exactly one result set, got ${
|
||||
bqrsInfo["result-sets"].length
|
||||
} for ${basename(queryPath)}`,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Octokit } from "@octokit/rest";
|
||||
import { Progress, CancellationToken } from "vscode";
|
||||
import { Credentials } from "../common/authentication";
|
||||
import { showAndLogWarningMessage } from "../common/vscode/log";
|
||||
import { extLogger } from "../common";
|
||||
|
||||
export async function getCodeSearchRepositories(
|
||||
query: string,
|
||||
@@ -53,6 +54,7 @@ async function provideOctokitWithThrottling(
|
||||
throttle: {
|
||||
onRateLimit: (retryAfter: number, options: any): boolean => {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Rate Limit detected for request ${options.method} ${options.url}. Retrying after ${retryAfter} seconds!`,
|
||||
);
|
||||
|
||||
@@ -60,6 +62,7 @@ async function provideOctokitWithThrottling(
|
||||
},
|
||||
onSecondaryRateLimit: (_retryAfter: number, options: any): void => {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Secondary Rate Limit detected for request ${options.method} ${options.url}`,
|
||||
);
|
||||
},
|
||||
|
||||
@@ -70,6 +70,7 @@ export async function promptImportInternetDatabase(
|
||||
if (item) {
|
||||
await commandManager.execute("codeQLDatabases.focus");
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
"Database downloaded and imported successfully.",
|
||||
);
|
||||
}
|
||||
@@ -115,6 +116,7 @@ export async function promptImportGithubDatabase(
|
||||
if (databaseItem) {
|
||||
await commandManager.execute("codeQLDatabases.focus");
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
"Database downloaded and imported successfully.",
|
||||
);
|
||||
return databaseItem;
|
||||
@@ -246,6 +248,7 @@ export async function importArchiveDatabase(
|
||||
if (item) {
|
||||
await commandManager.execute("codeQLDatabases.focus");
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
"Database unzipped and imported successfully.",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -281,6 +281,7 @@ export class DatabaseUI extends DisposableObject {
|
||||
await this.chooseAndSetDatabase(true, { progress, token });
|
||||
} catch (e) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(e),
|
||||
)`Failed to choose and set database: ${getErrorMessage(e)}`,
|
||||
@@ -418,6 +419,7 @@ export class DatabaseUI extends DisposableObject {
|
||||
await remove(dbDir);
|
||||
} catch (e) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(e),
|
||||
)`Failed to delete orphaned database: ${getErrorMessage(e)}`,
|
||||
@@ -430,6 +432,7 @@ export class DatabaseUI extends DisposableObject {
|
||||
if (failures.length) {
|
||||
const dirname = path_dirname(failures[0]);
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Failed to delete unused databases (${failures.join(
|
||||
", ",
|
||||
)}).\nTo delete unused databases, please remove them manually from the storage folder ${dirname}.`,
|
||||
@@ -445,6 +448,7 @@ export class DatabaseUI extends DisposableObject {
|
||||
await this.chooseAndSetDatabase(false, { progress, token });
|
||||
} catch (e: unknown) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(e),
|
||||
)`Failed to choose and set database: ${getErrorMessage(e)}`,
|
||||
|
||||
@@ -412,6 +412,7 @@ export class DatabaseManager extends DisposableObject {
|
||||
} catch (e) {
|
||||
// database list had an unexpected type - nothing to be done?
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(e),
|
||||
)`Database list loading failed: ${getErrorMessage(e)}`,
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
showAndLogInformationMessage,
|
||||
showAndLogWarningMessage,
|
||||
} from "../../common/vscode/log";
|
||||
import { extLogger } from "../../common";
|
||||
|
||||
export class DatabaseResolver {
|
||||
public static async resolveDatabaseContents(
|
||||
@@ -107,6 +108,7 @@ async function findDataset(parentDirectory: string): Promise<vscode.Uri> {
|
||||
const dbAbsolutePath = join(parentDirectory, dbRelativePaths[0]);
|
||||
if (dbRelativePaths.length > 1) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Found multiple dataset directories in database, using '${dbAbsolutePath}'.`,
|
||||
);
|
||||
}
|
||||
@@ -138,6 +140,7 @@ export async function findSourceArchive(
|
||||
}
|
||||
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
`Could not find source archive for database '${databasePath}'. Assuming paths are absolute.`,
|
||||
);
|
||||
return undefined;
|
||||
|
||||
@@ -38,6 +38,7 @@ import {
|
||||
showAndLogErrorMessage,
|
||||
showAndLogInformationMessage,
|
||||
} from "../../common/vscode/log";
|
||||
import { extLogger } from "../../common";
|
||||
|
||||
export interface RemoteDatabaseQuickPickItem extends QuickPickItem {
|
||||
remoteDatabaseKind: string;
|
||||
@@ -174,12 +175,18 @@ export class DbPanel extends DisposableObject {
|
||||
|
||||
const nwo = getNwoFromGitHubUrl(repoName) || repoName;
|
||||
if (!isValidGitHubNwo(nwo)) {
|
||||
void showAndLogErrorMessage(`Invalid GitHub repository: ${repoName}`);
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Invalid GitHub repository: ${repoName}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.dbManager.doesRemoteRepoExist(nwo, parentList)) {
|
||||
void showAndLogErrorMessage(`The repository '${nwo}' already exists`);
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`The repository '${nwo}' already exists`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -199,12 +206,18 @@ export class DbPanel extends DisposableObject {
|
||||
|
||||
const owner = getOwnerFromGitHubUrl(ownerName) || ownerName;
|
||||
if (!isValidGitHubOwner(owner)) {
|
||||
void showAndLogErrorMessage(`Invalid user or organization: ${owner}`);
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Invalid user or organization: ${owner}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.dbManager.doesRemoteOwnerExist(owner)) {
|
||||
void showAndLogErrorMessage(`The owner '${owner}' already exists`);
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`The owner '${owner}' already exists`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -223,7 +236,10 @@ export class DbPanel extends DisposableObject {
|
||||
}
|
||||
|
||||
if (this.dbManager.doesListExist(listKind, listName)) {
|
||||
void showAndLogErrorMessage(`The list '${listName}' already exists`);
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`The list '${listName}' already exists`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -287,7 +303,10 @@ export class DbPanel extends DisposableObject {
|
||||
}
|
||||
|
||||
if (this.dbManager.doesListExist(DbListKind.Local, newName)) {
|
||||
void showAndLogErrorMessage(`The list '${newName}' already exists`);
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`The list '${newName}' already exists`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -303,7 +322,10 @@ export class DbPanel extends DisposableObject {
|
||||
}
|
||||
|
||||
if (this.dbManager.doesLocalDbExist(newName, dbItem.parentListName)) {
|
||||
void showAndLogErrorMessage(`The database '${newName}' already exists`);
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`The database '${newName}' already exists`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -319,7 +341,10 @@ export class DbPanel extends DisposableObject {
|
||||
}
|
||||
|
||||
if (this.dbManager.doesListExist(DbListKind.Remote, newName)) {
|
||||
void showAndLogErrorMessage(`The list '${newName}' already exists`);
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`The list '${newName}' already exists`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -402,7 +427,7 @@ export class DbPanel extends DisposableObject {
|
||||
);
|
||||
|
||||
token.onCancellationRequested(() => {
|
||||
void showAndLogInformationMessage("Code search cancelled");
|
||||
void showAndLogInformationMessage(extLogger, "Code search cancelled");
|
||||
return;
|
||||
});
|
||||
|
||||
@@ -471,6 +496,7 @@ export class DbPanel extends DisposableObject {
|
||||
}
|
||||
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`An error occurred while setting up the controller repository: ${getErrorMessage(
|
||||
e,
|
||||
)}`,
|
||||
|
||||
@@ -10,6 +10,7 @@ import { getQuickEvalContext, validateQueryPath } from "../run-queries-shared";
|
||||
import * as CodeQLProtocol from "./debug-protocol";
|
||||
import { getErrorMessage } from "../pure/helpers-pure";
|
||||
import { showAndLogErrorMessage } from "../common/vscode/log";
|
||||
import { extLogger } from "../common";
|
||||
|
||||
/**
|
||||
* The CodeQL launch arguments, as specified in "launch.json".
|
||||
@@ -126,7 +127,7 @@ export class QLDebugConfigurationProvider
|
||||
// Any unhandled exception will result in an OS-native error message box, which seems ugly.
|
||||
// We'll just show a real VS Code error message, then return null to prevent the debug session
|
||||
// from starting.
|
||||
void showAndLogErrorMessage(getErrorMessage(e));
|
||||
void showAndLogErrorMessage(extLogger, getErrorMessage(e));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ import {
|
||||
QuickEvalCodeLensProvider,
|
||||
} from "./local-queries";
|
||||
import {
|
||||
BaseLogger,
|
||||
extLogger,
|
||||
ideServerLogger,
|
||||
ProgressReporter,
|
||||
@@ -193,9 +194,10 @@ function getCommands(
|
||||
}
|
||||
},
|
||||
]);
|
||||
void showAndLogInformationMessage("CodeQL Query Server restarted.", {
|
||||
outputLogger: queryServerLogger,
|
||||
});
|
||||
void showAndLogInformationMessage(
|
||||
queryServerLogger,
|
||||
"CodeQL Query Server restarted.",
|
||||
);
|
||||
},
|
||||
{
|
||||
title: "Restarting Query Server",
|
||||
@@ -215,7 +217,7 @@ function getCommands(
|
||||
extension?.packageJSON.version
|
||||
} \nCodeQL CLI version: ${await getCliVersion()} \nPlatform: ${platform()} ${arch()}`;
|
||||
await env.clipboard.writeText(text);
|
||||
void showAndLogInformationMessage(text);
|
||||
void showAndLogInformationMessage(extLogger, text);
|
||||
},
|
||||
"codeQL.authenticateToGitHub": async () => {
|
||||
/**
|
||||
@@ -225,6 +227,7 @@ function getCommands(
|
||||
const octokit = await app.credentials.getOctokit();
|
||||
const userInfo = await octokit.users.getAuthenticated();
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
`Authenticated to GitHub as user: ${userInfo.data.login}`,
|
||||
);
|
||||
},
|
||||
@@ -341,6 +344,7 @@ export async function activate(
|
||||
|
||||
registerErrorStubs([checkForUpdatesCommand], (command) => async () => {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Can't execute ${command}: waiting to finish loading CodeQL CLI.`,
|
||||
);
|
||||
});
|
||||
@@ -428,6 +432,7 @@ export async function activate(
|
||||
}
|
||||
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`You are using an unsupported version of the CodeQL CLI (${ver}). ` +
|
||||
`The minimum supported version is ${CliVersionConstraint.OLDEST_SUPPORTED_CLI_VERSION}. ` +
|
||||
`Please upgrade to a newer version of the CodeQL CLI.`,
|
||||
@@ -449,7 +454,7 @@ async function installOrUpdateDistributionWithProgressTitle(
|
||||
const minSecondsSinceLastUpdateCheck = config.isUserInitiated ? 0 : 86400;
|
||||
const noUpdatesLoggingFunc = config.shouldDisplayMessageWhenNoUpdates
|
||||
? showAndLogInformationMessage
|
||||
: async (message: string) => void extLogger.log(message);
|
||||
: async (logger: BaseLogger, message: string) => void logger.log(message);
|
||||
const result =
|
||||
await distributionManager.checkForUpdatesToExtensionManagedDistribution(
|
||||
minSecondsSinceLastUpdateCheck,
|
||||
@@ -467,10 +472,11 @@ async function installOrUpdateDistributionWithProgressTitle(
|
||||
);
|
||||
break;
|
||||
case DistributionUpdateCheckResultKind.AlreadyUpToDate:
|
||||
await noUpdatesLoggingFunc("CodeQL CLI already up to date.");
|
||||
await noUpdatesLoggingFunc(extLogger, "CodeQL CLI already up to date.");
|
||||
break;
|
||||
case DistributionUpdateCheckResultKind.InvalidLocation:
|
||||
await noUpdatesLoggingFunc(
|
||||
extLogger,
|
||||
"CodeQL CLI is installed externally so could not be updated.",
|
||||
);
|
||||
break;
|
||||
@@ -502,6 +508,7 @@ async function installOrUpdateDistributionWithProgressTitle(
|
||||
|
||||
await ctx.globalState.update(shouldUpdateOnNextActivationKey, false);
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
`CodeQL CLI updated to version "${result.updatedRelease.name}".`,
|
||||
);
|
||||
}
|
||||
@@ -556,6 +563,7 @@ async function installOrUpdateDistribution(
|
||||
|
||||
if (e instanceof GithubRateLimitedError) {
|
||||
void alertFunction(
|
||||
extLogger,
|
||||
`Rate limited while trying to ${taskDescription}. Please try again after ` +
|
||||
`your rate limit window resets at ${e.rateLimitResetDate.toLocaleString(
|
||||
env.language,
|
||||
@@ -563,10 +571,11 @@ async function installOrUpdateDistribution(
|
||||
);
|
||||
} else if (e instanceof GithubApiError) {
|
||||
void alertFunction(
|
||||
extLogger,
|
||||
`Encountered GitHub API error while trying to ${taskDescription}. ${e}`,
|
||||
);
|
||||
}
|
||||
void alertFunction(`Unable to ${taskDescription}. ${e}`);
|
||||
void alertFunction(extLogger, `Unable to ${taskDescription}. ${e}`);
|
||||
} finally {
|
||||
isInstallingOrUpdatingDistribution = false;
|
||||
}
|
||||
@@ -598,6 +607,7 @@ async function getDistributionDisplayingDistributionWarnings(
|
||||
})();
|
||||
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`The current version of the CodeQL CLI (${result.version.raw}) ` +
|
||||
`is incompatible with this extension. ${fixGuidanceMessage}`,
|
||||
);
|
||||
@@ -605,12 +615,16 @@ async function getDistributionDisplayingDistributionWarnings(
|
||||
}
|
||||
case FindDistributionResultKind.UnknownCompatibilityDistribution:
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
"Compatibility with the configured CodeQL CLI could not be determined. " +
|
||||
"You may experience problems using the extension.",
|
||||
);
|
||||
break;
|
||||
case FindDistributionResultKind.NoDistribution:
|
||||
void showAndLogErrorMessage("The CodeQL CLI could not be found.");
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
"The CodeQL CLI could not be found.",
|
||||
);
|
||||
break;
|
||||
default:
|
||||
assertNever(result);
|
||||
@@ -652,14 +666,17 @@ async function installOrUpdateThenTryActivate(
|
||||
|
||||
if (distributionResult.kind === FindDistributionResultKind.NoDistribution) {
|
||||
registerErrorStubs([checkForUpdatesCommand], (command) => async () => {
|
||||
void extLogger.log(`Can't execute ${command}: missing CodeQL CLI.`);
|
||||
const showLogName = "Show Log";
|
||||
const installActionName = "Install CodeQL CLI";
|
||||
const chosenAction = await showAndLogErrorMessage(
|
||||
const chosenAction = await Window.showErrorMessage(
|
||||
`Can't execute ${command}: missing CodeQL CLI.`,
|
||||
{
|
||||
items: [installActionName],
|
||||
},
|
||||
showLogName,
|
||||
installActionName,
|
||||
);
|
||||
if (chosenAction === installActionName) {
|
||||
if (chosenAction === showLogName) {
|
||||
extLogger.show();
|
||||
} else if (chosenAction === installActionName) {
|
||||
await installOrUpdateThenTryActivate(
|
||||
ctx,
|
||||
app,
|
||||
@@ -1116,6 +1133,7 @@ async function showResultsForComparison(
|
||||
await compareView.showResults(from, to);
|
||||
} catch (e) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(asError(e))`Failed to show results: ${getErrorMessage(
|
||||
e,
|
||||
)}`,
|
||||
@@ -1141,7 +1159,7 @@ function addUnhandledRejectionListener() {
|
||||
)`Unhandled error: ${getErrorMessage(error)}`;
|
||||
// Add a catch so that showAndLogExceptionWithTelemetry fails, we avoid
|
||||
// triggering "unhandledRejection" and avoid an infinite loop
|
||||
showAndLogExceptionWithTelemetry(message).catch(
|
||||
showAndLogExceptionWithTelemetry(extLogger, message).catch(
|
||||
(telemetryError: unknown) => {
|
||||
void extLogger.log(
|
||||
`Failed to send error telemetry: ${getErrorMessage(
|
||||
@@ -1250,6 +1268,7 @@ async function assertVSCodeVersionGreaterThan(
|
||||
const parsedMinVersion = parse(minVersion);
|
||||
if (!parsedVersion || !parsedMinVersion) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Could not do a version check of vscode because could not parse version number: actual vscode version ${vscodeVersion} or minimum supported vscode version ${minVersion}.`,
|
||||
);
|
||||
return;
|
||||
@@ -1269,6 +1288,7 @@ async function assertVSCodeVersionGreaterThan(
|
||||
}
|
||||
} catch (e) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Could not do a version check because of an error: ${getErrorMessage(e)}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import { asError, getErrorMessage } from "../../pure/helpers-pure";
|
||||
import { redactableError } from "../../pure/errors";
|
||||
import { AstViewerCommands } from "../../common/commands";
|
||||
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/log";
|
||||
import { extLogger } from "../../common";
|
||||
|
||||
export interface AstItem {
|
||||
id: BqrsId;
|
||||
@@ -145,6 +146,7 @@ export class AstViewer extends DisposableObject {
|
||||
},
|
||||
(error: unknown) =>
|
||||
showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(error),
|
||||
)`Failed to reveal AST: ${getErrorMessage(error)}`,
|
||||
@@ -208,6 +210,7 @@ export class AstViewer extends DisposableObject {
|
||||
},
|
||||
(error: unknown) =>
|
||||
showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(error),
|
||||
)`Failed to reveal AST: ${getErrorMessage(error)}`,
|
||||
|
||||
@@ -102,7 +102,7 @@ current library path (tried searching the following packs: ${joinedPacksToSearch
|
||||
Try upgrading the CodeQL libraries. If that doesn't work, then ${keyTypeName} queries are not yet available \
|
||||
for this language.`;
|
||||
|
||||
void showAndLogExceptionWithTelemetry(error);
|
||||
void showAndLogExceptionWithTelemetry(extLogger, error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getErrorMessage } from "../pure/helpers-pure";
|
||||
import { redactableError } from "../pure/errors";
|
||||
import { AppCommandManager, QueryEditorCommands } from "../common/commands";
|
||||
import { showAndLogExceptionWithTelemetry } from "../common/vscode/log";
|
||||
import { extLogger } from "../common";
|
||||
|
||||
type QueryEditorOptions = {
|
||||
commandManager: AppCommandManager;
|
||||
@@ -79,7 +80,7 @@ async function previewQueryHelp(
|
||||
)
|
||||
? redactableError`Could not generate markdown from ${pathToQhelp}: Bad formatting in .qhelp file.`
|
||||
: redactableError`Could not open a preview of the generated file (${absolutePathToMd}).`;
|
||||
void showAndLogExceptionWithTelemetry(errorMessage, {
|
||||
void showAndLogExceptionWithTelemetry(extLogger, errorMessage, {
|
||||
fullMessage: `${errorMessage}\n${getErrorMessage(e)}`,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -323,6 +323,7 @@ export class LocalQueries extends DisposableObject {
|
||||
|
||||
if (this.queryRunner.customLogDirectory) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Custom log directories are no longer supported. The "codeQL.runningQueries.customLogDirectory" setting is deprecated. Unset the setting to stop seeing this message. Query logs saved to ${outputDir.logPath}`,
|
||||
);
|
||||
}
|
||||
@@ -469,6 +470,7 @@ export class LocalQueries extends DisposableObject {
|
||||
let filteredDBs = this.databaseManager.databaseItems;
|
||||
if (filteredDBs.length === 0) {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
"No databases found. Please add a suitable database to your workspace.",
|
||||
);
|
||||
return;
|
||||
@@ -481,6 +483,7 @@ export class LocalQueries extends DisposableObject {
|
||||
);
|
||||
if (filteredDBs.length === 0) {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`No databases found for language ${queryLanguage}. Please add a suitable database to your workspace.`,
|
||||
);
|
||||
return;
|
||||
@@ -519,13 +522,14 @@ export class LocalQueries extends DisposableObject {
|
||||
if (skippedDatabases.length > 0) {
|
||||
void extLogger.log(`Errors:\n${errors.join("\n")}`);
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`The following databases were skipped:\n${skippedDatabases.join(
|
||||
"\n",
|
||||
)}.\nFor details about the errors, see the logs.`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
void showAndLogErrorMessage("No databases selected.");
|
||||
void showAndLogErrorMessage(extLogger, "No databases selected.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BaseLogger, Logger } from "../common";
|
||||
import { BaseLogger, extLogger, Logger } from "../common";
|
||||
import { CoreQueryResults } from "../query-server";
|
||||
import { QueryHistoryManager } from "../query-history/query-history-manager";
|
||||
import { DatabaseItem } from "../databases/local-databases";
|
||||
@@ -119,6 +119,7 @@ export class LocalQueryRun {
|
||||
// Raw evaluator log was not found. Notify the user, unless we know why it wasn't found.
|
||||
if (resultType === QueryResultType.SUCCESS) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Failed to write structured evaluator log to ${outputDir.evalLogPath}.`,
|
||||
);
|
||||
} else {
|
||||
@@ -155,7 +156,7 @@ export class LocalQueryRun {
|
||||
const message = results.message
|
||||
? redactableError`Failed to run query: ${results.message}`
|
||||
: redactableError`Failed to run query`;
|
||||
void showAndLogExceptionWithTelemetry(message);
|
||||
void showAndLogExceptionWithTelemetry(extLogger, message);
|
||||
}
|
||||
const message = formatResultMessage(results);
|
||||
const successful = results.resultType === QueryResultType.SUCCESS;
|
||||
|
||||
@@ -40,7 +40,7 @@ import {
|
||||
getDefaultResultSetName,
|
||||
ParsedResultSets,
|
||||
} from "../pure/interface-types";
|
||||
import { Logger } from "../common";
|
||||
import { extLogger, Logger } from "../common";
|
||||
import {
|
||||
CompletedQueryInfo,
|
||||
interpretResultsSarif,
|
||||
@@ -319,6 +319,7 @@ export class ResultsView extends AbstractWebview<
|
||||
break;
|
||||
case "unhandledError":
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
msg.error,
|
||||
)`Unhandled error in results view: ${msg.error.message}`,
|
||||
@@ -329,6 +330,7 @@ export class ResultsView extends AbstractWebview<
|
||||
}
|
||||
} catch (e) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(e),
|
||||
)`Error handling message from results view: ${getErrorMessage(e)}`,
|
||||
@@ -378,6 +380,7 @@ export class ResultsView extends AbstractWebview<
|
||||
): Promise<void> {
|
||||
if (this._displayedQuery === undefined) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`Failed to sort results since evaluation info was unknown.`,
|
||||
);
|
||||
return;
|
||||
@@ -396,6 +399,7 @@ export class ResultsView extends AbstractWebview<
|
||||
): Promise<void> {
|
||||
if (this._displayedQuery === undefined) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`Failed to sort results since evaluation info was unknown.`,
|
||||
);
|
||||
return;
|
||||
@@ -806,6 +810,7 @@ export class ResultsView extends AbstractWebview<
|
||||
// If interpretation fails, accept the error and continue
|
||||
// trying to render uninterpreted results anyway.
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(e),
|
||||
)`Showing raw results instead of interpreted ones due to an error. ${getErrorMessage(
|
||||
|
||||
@@ -87,9 +87,13 @@ export async function handleDownloadPacks(
|
||||
});
|
||||
try {
|
||||
await cliServer.packDownload(packsToDownload);
|
||||
void showAndLogInformationMessage("Finished downloading packs.");
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
"Finished downloading packs.",
|
||||
);
|
||||
} catch (error) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(error),
|
||||
)`Unable to download all packs. See log for more details.`,
|
||||
@@ -165,6 +169,7 @@ export async function handleInstallPackDependencies(
|
||||
);
|
||||
} else {
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
"Finished installing pack dependencies.",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { asError, getErrorMessage } from "../pure/helpers-pure";
|
||||
import { redactableError } from "../pure/errors";
|
||||
import { EvalLogViewerCommands } from "../common/commands";
|
||||
import { showAndLogExceptionWithTelemetry } from "../common/vscode/log";
|
||||
import { extLogger } from "../common";
|
||||
|
||||
export interface EvalLogTreeItem {
|
||||
label?: string;
|
||||
@@ -109,6 +110,7 @@ export class EvalLogViewer extends DisposableObject {
|
||||
},
|
||||
(err: unknown) =>
|
||||
showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(err),
|
||||
)`Failed to reveal tree view: ${getErrorMessage(err)}`,
|
||||
|
||||
@@ -628,6 +628,7 @@ export class QueryHistoryManager extends DisposableObject {
|
||||
toItem = await this.findOtherQueryToCompare(fromItem, multiSelect);
|
||||
} catch (e) {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
`Failed to compare queries: ${getErrorMessage(e)}`,
|
||||
);
|
||||
}
|
||||
@@ -672,7 +673,7 @@ export class QueryHistoryManager extends DisposableObject {
|
||||
item.completedQuery.logFileLocation,
|
||||
);
|
||||
} else {
|
||||
void showAndLogWarningMessage("No log file available");
|
||||
void showAndLogWarningMessage(extLogger, "No log file available");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,18 +741,21 @@ export class QueryHistoryManager extends DisposableObject {
|
||||
|
||||
private warnNoEvalLogs() {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Evaluator log, summary, and viewer are not available for this run. Perhaps it failed before evaluation, or you are running with a version of CodeQL before ' + ${CliVersionConstraint.CLI_VERSION_WITH_PER_QUERY_EVAL_LOG}?`,
|
||||
);
|
||||
}
|
||||
|
||||
private warnInProgressEvalLogSummary() {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
'The evaluator log summary is still being generated for this run. Please try again later. The summary generation process is tracked in the "CodeQL Extension Log" view.',
|
||||
);
|
||||
}
|
||||
|
||||
private warnInProgressEvalLogViewer() {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
"The viewer's data is still being generated for this run. Please try again or re-run the query.",
|
||||
);
|
||||
}
|
||||
@@ -868,6 +872,7 @@ export class QueryHistoryManager extends DisposableObject {
|
||||
} else {
|
||||
const label = this.labelProvider.getLabel(item);
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
`Query ${label} has no interpreted results.`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { QueryHistoryDto, QueryHistoryItemDto } from "./query-history-dto";
|
||||
import { mapQueryHistoryToDomainModel } from "./query-history-dto-mapper";
|
||||
import { mapQueryHistoryToDto } from "./query-history-domain-mapper";
|
||||
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/log";
|
||||
import { extLogger } from "../../common";
|
||||
|
||||
const ALLOWED_QUERY_HISTORY_VERSIONS = [1, 2];
|
||||
|
||||
@@ -30,6 +31,7 @@ export async function readQueryHistoryFromFile(
|
||||
|
||||
if (!ALLOWED_QUERY_HISTORY_VERSIONS.includes(obj.version)) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`Can't parse query history. Unsupported query history format: v${obj.version}.`,
|
||||
);
|
||||
return [];
|
||||
@@ -65,6 +67,7 @@ export async function readQueryHistoryFromFile(
|
||||
return filteredDomainModels;
|
||||
} catch (e) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(asError(e))`Error loading query history.`,
|
||||
{
|
||||
fullMessage: `Error loading query history.\n${getErrorStack(e)}`,
|
||||
|
||||
@@ -321,6 +321,7 @@ export async function compileAndRunQueryAgainstDatabaseCore(
|
||||
): Promise<CoreQueryResults> {
|
||||
if (extensionPacks !== undefined && extensionPacks.length > 0) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
"Legacy query server does not support extension packs.",
|
||||
);
|
||||
}
|
||||
@@ -386,6 +387,7 @@ export async function compileAndRunQueryAgainstDatabaseCore(
|
||||
}
|
||||
} catch (e) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(e),
|
||||
)`Couldn't resolve available ML models for ${qlProgram.queryPath}. Running the query without any ML models: ${e}.`,
|
||||
@@ -444,7 +446,7 @@ export async function compileAndRunQueryAgainstDatabaseCore(
|
||||
? redactableError`${result.message}`
|
||||
: redactableError`Failed to run query`;
|
||||
void extLogger.log(error.fullMessage);
|
||||
void showAndLogExceptionWithTelemetry(error);
|
||||
void showAndLogExceptionWithTelemetry(extLogger, error);
|
||||
}
|
||||
|
||||
return translateLegacyResult(result);
|
||||
|
||||
@@ -206,6 +206,7 @@ export async function upgradeDatabaseExplicit(
|
||||
);
|
||||
} catch (e) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
asError(e),
|
||||
)`Compilation of database upgrades failed: ${getErrorMessage(e)}`,
|
||||
@@ -220,6 +221,7 @@ export async function upgradeDatabaseExplicit(
|
||||
? redactableError`${compileUpgradeResult.error}`
|
||||
: redactableError`[no error message available]`;
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`Compilation of database upgrades failed: ${error}`,
|
||||
);
|
||||
return;
|
||||
@@ -253,6 +255,7 @@ export async function upgradeDatabaseExplicit(
|
||||
return result;
|
||||
} catch (e) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(asError(e))`Database upgrade failed: ${getErrorMessage(
|
||||
e,
|
||||
)}`,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { CancellationToken } from "vscode";
|
||||
import { createMessageConnection, RequestType } from "vscode-jsonrpc/node";
|
||||
import * as cli from "../codeql-cli/cli";
|
||||
import { QueryServerConfig } from "../config";
|
||||
import { Logger, ProgressReporter } from "../common";
|
||||
import { extLogger, Logger, ProgressReporter } from "../common";
|
||||
import {
|
||||
progress,
|
||||
ProgressMessage,
|
||||
@@ -131,6 +131,7 @@ export class QueryServerClient extends DisposableObject {
|
||||
);
|
||||
} else {
|
||||
void showAndLogErrorMessage(
|
||||
extLogger,
|
||||
"The CodeQL query server has unexpectedly terminated too many times. Please check the logs for errors. You can manually restart the query server using the command 'CodeQL: Restart query server'.",
|
||||
);
|
||||
// Make sure we dispose anyway to reject all pending requests.
|
||||
|
||||
@@ -5,7 +5,7 @@ import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
|
||||
import { asError, getErrorMessage } from "../pure/helpers-pure";
|
||||
import { redactableError } from "../pure/errors";
|
||||
import { access } from "fs-extra";
|
||||
import { BaseLogger } from "../common";
|
||||
import { BaseLogger, extLogger } from "../common";
|
||||
import { DisposableObject } from "../pure/disposable-object";
|
||||
import {
|
||||
showAndLogExceptionWithTelemetry,
|
||||
@@ -88,6 +88,7 @@ export class TestRunner extends DisposableObject {
|
||||
// Explorer UI swallows any thrown exception without reporting it to the user.
|
||||
// So we need to display the error message ourselves and then rethrow.
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(asError(e))`Cannot remove database ${
|
||||
database.name
|
||||
}: ${getErrorMessage(e)}`,
|
||||
@@ -128,7 +129,10 @@ export class TestRunner extends DisposableObject {
|
||||
// This method is invoked from Test Explorer UI, and testing indicates that Test
|
||||
// Explorer UI swallows any thrown exception without reporting it to the user.
|
||||
// So we need to display the error message ourselves and then rethrow.
|
||||
void showAndLogWarningMessage(`Cannot reopen database ${uri}: ${e}`);
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Cannot reopen database ${uri}: ${e}`,
|
||||
);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ export class QueryEvaluationInfo extends QueryOutputDir {
|
||||
): Promise<boolean> {
|
||||
const resultSet = await this.chooseResultSet(cliServer);
|
||||
if (!resultSet) {
|
||||
void showAndLogWarningMessage("Query has no result set.");
|
||||
void showAndLogWarningMessage(extLogger, "Query has no result set.");
|
||||
return false;
|
||||
}
|
||||
let stopDecoding = false;
|
||||
@@ -659,6 +659,7 @@ async function generateHumanReadableLogSummary(
|
||||
return true;
|
||||
} catch (e) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Failed to generate human-readable structured evaluator log summary. Reason: ${getErrorMessage(
|
||||
e,
|
||||
)}`,
|
||||
@@ -682,6 +683,7 @@ export async function logEndSummary(
|
||||
void logger.log(endSummaryContent);
|
||||
} catch (e) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Could not read structured evaluator log end of summary file at ${endSummary}.`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { DataFlowPaths } from "./shared/data-flow-paths";
|
||||
import { redactableError } from "../pure/errors";
|
||||
import { showAndLogExceptionWithTelemetry } from "../common/vscode/log";
|
||||
import { extLogger } from "../common";
|
||||
|
||||
export class DataFlowPathsView extends AbstractWebview<
|
||||
ToDataFlowPathsMessage,
|
||||
@@ -59,6 +60,7 @@ export class DataFlowPathsView extends AbstractWebview<
|
||||
break;
|
||||
case "unhandledError":
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
msg.error,
|
||||
)`Unhandled error in data flow paths view: ${msg.error.message}`,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { URLSearchParams } from "url";
|
||||
import { SHOW_QUERY_TEXT_MSG } from "../query-history/query-history-manager";
|
||||
import { VariantAnalysisManager } from "./variant-analysis-manager";
|
||||
import { showAndLogWarningMessage } from "../common/vscode/log";
|
||||
import { extLogger } from "../common";
|
||||
|
||||
export const createVariantAnalysisContentProvider = (
|
||||
variantAnalysisManager: VariantAnalysisManager,
|
||||
@@ -13,6 +14,7 @@ export const createVariantAnalysisContentProvider = (
|
||||
const variantAnalysisIdString = params.get("variantAnalysisId");
|
||||
if (!variantAnalysisIdString) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
"Unable to show query text. No variant analysis ID provided.",
|
||||
);
|
||||
return undefined;
|
||||
@@ -24,6 +26,7 @@ export const createVariantAnalysisContentProvider = (
|
||||
);
|
||||
if (!variantAnalysis) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
"Unable to show query text. No variant analysis found.",
|
||||
);
|
||||
return undefined;
|
||||
|
||||
@@ -256,6 +256,7 @@ export class VariantAnalysisManager
|
||||
await this.onVariantAnalysisSubmitted(processedVariantAnalysis);
|
||||
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
`Variant analysis ${processedVariantAnalysis.query.name} submitted for processing`,
|
||||
);
|
||||
|
||||
@@ -328,6 +329,7 @@ export class VariantAnalysisManager
|
||||
public async showView(variantAnalysisId: number): Promise<void> {
|
||||
if (!this.variantAnalyses.get(variantAnalysisId)) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError`No variant analysis found with id: ${variantAnalysisId}.`,
|
||||
);
|
||||
}
|
||||
@@ -347,6 +349,7 @@ export class VariantAnalysisManager
|
||||
const variantAnalysis = await this.getVariantAnalysis(variantAnalysisId);
|
||||
if (!variantAnalysis) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
"Could not open variant analysis query text. Variant analysis not found.",
|
||||
);
|
||||
return;
|
||||
@@ -367,6 +370,7 @@ export class VariantAnalysisManager
|
||||
await Window.showTextDocument(doc, { preview: false });
|
||||
} catch (error) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
"Could not open variant analysis query text. Failed to open text document.",
|
||||
);
|
||||
}
|
||||
@@ -377,6 +381,7 @@ export class VariantAnalysisManager
|
||||
|
||||
if (!variantAnalysis) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
"Could not open variant analysis query file",
|
||||
);
|
||||
return;
|
||||
@@ -389,6 +394,7 @@ export class VariantAnalysisManager
|
||||
await Window.showTextDocument(textDocument, ViewColumn.One);
|
||||
} catch (error) {
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
`Could not open file: ${variantAnalysis.query.filePath}`,
|
||||
);
|
||||
}
|
||||
@@ -701,6 +707,7 @@ export class VariantAnalysisManager
|
||||
}
|
||||
|
||||
void showAndLogInformationMessage(
|
||||
extLogger,
|
||||
"Cancelling variant analysis. This may take a while.",
|
||||
);
|
||||
await cancelVariantAnalysis(this.app.credentials, variantAnalysis);
|
||||
|
||||
@@ -98,7 +98,7 @@ export class VariantAnalysisMonitor extends DisposableObject {
|
||||
if (lastErrorShown === errorMessage) {
|
||||
void extLogger.log(message);
|
||||
} else {
|
||||
void showAndLogWarningMessage(message);
|
||||
void showAndLogWarningMessage(extLogger, message);
|
||||
lastErrorShown = errorMessage;
|
||||
}
|
||||
|
||||
|
||||
@@ -166,6 +166,7 @@ export class VariantAnalysisView
|
||||
break;
|
||||
case "unhandledError":
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
extLogger,
|
||||
redactableError(
|
||||
msg.error,
|
||||
)`Unhandled error in variant analysis results view: ${msg.error.message}`,
|
||||
@@ -186,7 +187,10 @@ export class VariantAnalysisView
|
||||
);
|
||||
|
||||
if (!variantAnalysis) {
|
||||
void showAndLogWarningMessage("Unable to load variant analysis");
|
||||
void showAndLogWarningMessage(
|
||||
extLogger,
|
||||
"Unable to load variant analysis",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ describe("Packaging commands", () => {
|
||||
|
||||
expect(showAndLogExceptionWithTelemetrySpy).toHaveBeenCalled();
|
||||
expect(
|
||||
showAndLogExceptionWithTelemetrySpy.mock.calls[0][0].fullMessage,
|
||||
showAndLogExceptionWithTelemetrySpy.mock.calls[0][1].fullMessage,
|
||||
).toEqual("Unable to download all packs. See log for more details.");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user