Merge pull request #3004 from github/koesie10/redactable-error-stack

Show stack for redactable error in log
This commit is contained in:
Koen Vlaswinkel 2023-10-23 12:04:08 +02:00 коммит произвёл GitHub
Родитель 8011481de2 4ca14f89df
Коммит 41aeb47a4e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 46 добавлений и 15 удалений

Просмотреть файл

@ -22,6 +22,14 @@ export class RedactableError extends Error {
.join(""); .join("");
} }
public get fullMessageWithStack(): string {
if (!this.stack) {
return this.fullMessage;
}
return `${this.fullMessage}\n${this.stack}`;
}
public get redactedMessage(): string { public get redactedMessage(): string {
return this.strings return this.strings
.map((s, i) => s + (this.hasValue(i) ? this.getRedactedValue(i) : "")) .map((s, i) => s + (this.hasValue(i) ? this.getRedactedValue(i) : ""))

Просмотреть файл

@ -112,5 +112,5 @@ export async function showAndLogExceptionWithTelemetry(
options: ShowAndLogExceptionOptions = {}, options: ShowAndLogExceptionOptions = {},
): Promise<void> { ): Promise<void> {
telemetry?.sendError(error, options.extraTelemetryProperties); telemetry?.sendError(error, options.extraTelemetryProperties);
return showAndLogErrorMessage(logger, error.fullMessage, options); return showAndLogErrorMessage(logger, error.fullMessageWithStack, options);
} }

Просмотреть файл

@ -6,11 +6,7 @@ import {
showAndLogExceptionWithTelemetry, showAndLogExceptionWithTelemetry,
} from "../logging"; } from "../logging";
import { extLogger } from "../logging/vscode"; import { extLogger } from "../logging/vscode";
import { import { asError, getErrorMessage } from "../../common/helpers-pure";
asError,
getErrorMessage,
getErrorStack,
} from "../../common/helpers-pure";
import { redactableError } from "../../common/errors"; import { redactableError } from "../../common/errors";
import { UserCancellationException } from "./progress"; import { UserCancellationException } from "./progress";
import { telemetryListener } from "./telemetry"; import { telemetryListener } from "./telemetry";
@ -66,10 +62,7 @@ export function registerCommandWithErrorHandling(
} }
} else { } else {
// Include the full stack in the error log only. // Include the full stack in the error log only.
const errorStack = getErrorStack(e); const fullMessage = errorMessage.fullMessageWithStack;
const fullMessage = errorStack
? `${errorMessage.fullMessage}\n${errorStack}`
: errorMessage.fullMessage;
void showAndLogExceptionWithTelemetry(logger, telemetry, errorMessage, { void showAndLogExceptionWithTelemetry(logger, telemetry, errorMessage, {
fullMessage, fullMessage,
extraTelemetryProperties: { extraTelemetryProperties: {

Просмотреть файл

@ -1170,10 +1170,7 @@ function addUnhandledRejectionListener() {
const message = redactableError( const message = redactableError(
asError(error), asError(error),
)`Unhandled error: ${getErrorMessage(error)}`; )`Unhandled error: ${getErrorMessage(error)}`;
const stack = getErrorStack(error); const fullMessage = message.fullMessageWithStack;
const fullMessage = stack
? `Unhandled error: ${stack}`
: message.fullMessage;
// Add a catch so that showAndLogExceptionWithTelemetry fails, we avoid // Add a catch so that showAndLogExceptionWithTelemetry fails, we avoid
// triggering "unhandledRejection" and avoid an infinite loop // triggering "unhandledRejection" and avoid an infinite loop

Просмотреть файл

@ -441,7 +441,6 @@ export async function compileAndRunQueryAgainstDatabaseCore(
const error = result.message const error = result.message
? redactableError`${result.message}` ? redactableError`${result.message}`
: redactableError`Failed to run query`; : redactableError`Failed to run query`;
void extLogger.log(error.fullMessage);
void showAndLogExceptionWithTelemetry( void showAndLogExceptionWithTelemetry(
extLogger, extLogger,
telemetryListener, telemetryListener,

Просмотреть файл

@ -19,6 +19,40 @@ describe("errorMessage", () => {
).toEqual("Failed to create database foo"); ).toEqual("Failed to create database foo");
}); });
it("fullMessageWithStack includes the stack", () => {
expect(
redactableError`Failed to create database ${"foo"}`.fullMessageWithStack,
).toMatch(
/^Failed to create database foo\nError: Failed to create database foo\n +at redactableError \(/,
);
});
it("fullMessageWithStack includes the cause stack for given error", () => {
function myRealFunction() {
throw new Error("Internal error");
}
let error: Error;
try {
myRealFunction();
fail("Expected an error to be thrown");
} catch (e: unknown) {
if (!(e instanceof Error)) {
throw new Error("Expected an Error to be thrown");
}
error = e;
}
expect(
redactableError(error)`Failed to create database ${"foo"}`
.fullMessageWithStack,
).toMatch(
/^Failed to create database foo\nError: Internal error\n +at myRealFunction \(/,
);
});
it("redactedMessage redacts the given message", () => { it("redactedMessage redacts the given message", () => {
expect( expect(
redactableError`Failed to create database ${"foo"}`.redactedMessage, redactableError`Failed to create database ${"foo"}`.redactedMessage,