Prompt user to report issue after single fatal error on insiders

This commit is contained in:
Matt Bierner 2020-03-04 19:25:09 -08:00
parent 36141fa1f3
commit 81c95f2e5c

View file

@ -108,6 +108,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
private serverState: ServerState.State = ServerState.None; private serverState: ServerState.State = ServerState.None;
private lastStart: number; private lastStart: number;
private numberRestarts: number; private numberRestarts: number;
private _isPromptingAfterCrash = false;
private isRestarting: boolean = false; private isRestarting: boolean = false;
private hasServerFatallyCrashedTooManyTimes = false; private hasServerFatallyCrashedTooManyTimes = false;
private readonly loadingIndicator = new ServerInitializingIndicator(); private readonly loadingIndicator = new ServerInitializingIndicator();
@ -323,12 +324,12 @@ export default class TypeScriptServiceClient extends Disposable implements IType
} }
const apiVersion = version.apiVersion || API.defaultVersion; const apiVersion = version.apiVersion || API.defaultVersion;
this.onDidChangeTypeScriptVersion(version);
let mytoken = ++this.token; let mytoken = ++this.token;
const handle = this.typescriptServerSpawner.spawn(version, this.configuration, this.pluginManager, { const handle = this.typescriptServerSpawner.spawn(version, this.configuration, this.pluginManager, {
onFatalError: (command, err) => this.fatalError(command, err), onFatalError: (command, err) => this.fatalError(command, err),
}); });
this.serverState = new ServerState.Running(handle, apiVersion, undefined, true); this.serverState = new ServerState.Running(handle, apiVersion, undefined, true);
this.onDidChangeTypeScriptVersion(version);
this.lastStart = Date.now(); this.lastStart = Date.now();
/* __GDPR__ /* __GDPR__
@ -515,14 +516,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType
private serviceExited(restart: boolean): void { private serviceExited(restart: boolean): void {
this.loadingIndicator.reset(); this.loadingIndicator.reset();
enum MessageAction {
reportIssue
}
interface MyMessageItem extends vscode.MessageItem {
id: MessageAction;
}
const previousState = this.serverState; const previousState = this.serverState;
this.serverState = ServerState.None; this.serverState = ServerState.None;
@ -530,19 +523,22 @@ export default class TypeScriptServiceClient extends Disposable implements IType
const diff = Date.now() - this.lastStart; const diff = Date.now() - this.lastStart;
this.numberRestarts++; this.numberRestarts++;
let startService = true; let startService = true;
const reportIssueItem: vscode.MessageItem = {
title: localize('serverDiedReportIssue', 'Report Issue'),
};
let prompt: Thenable<undefined | vscode.MessageItem> | undefined = undefined;
if (this.numberRestarts > 5) { if (this.numberRestarts > 5) {
let prompt: Thenable<MyMessageItem | undefined> | undefined = undefined;
this.numberRestarts = 0; this.numberRestarts = 0;
if (diff < 10 * 1000 /* 10 seconds */) { if (diff < 10 * 1000 /* 10 seconds */) {
this.lastStart = Date.now(); this.lastStart = Date.now();
startService = false; startService = false;
this.hasServerFatallyCrashedTooManyTimes = true; this.hasServerFatallyCrashedTooManyTimes = true;
prompt = vscode.window.showErrorMessage<MyMessageItem>( prompt = vscode.window.showErrorMessage(
localize('serverDiedAfterStart', 'The TypeScript language service died 5 times right after it got started. The service will not be restarted.'), localize('serverDiedAfterStart', 'The TypeScript language service died 5 times right after it got started. The service will not be restarted.'),
{ reportIssueItem);
title: localize('serverDiedReportIssue', 'Report Issue'),
id: MessageAction.reportIssue,
});
/* __GDPR__ /* __GDPR__
"serviceExited" : { "serviceExited" : {
"${include}": [ "${include}": [
@ -553,25 +549,32 @@ export default class TypeScriptServiceClient extends Disposable implements IType
this.logTelemetry('serviceExited'); this.logTelemetry('serviceExited');
} else if (diff < 60 * 1000 * 5 /* 5 Minutes */) { } else if (diff < 60 * 1000 * 5 /* 5 Minutes */) {
this.lastStart = Date.now(); this.lastStart = Date.now();
prompt = vscode.window.showWarningMessage<MyMessageItem>( prompt = vscode.window.showWarningMessage(
localize('serverDied', 'The TypeScript language service died unexpectedly 5 times in the last 5 Minutes.'), localize('serverDied', 'The TypeScript language service died unexpectedly 5 times in the last 5 Minutes.'),
{ reportIssueItem);
title: localize('serverDiedReportIssue', 'Report Issue'),
id: MessageAction.reportIssue
});
} }
if (prompt) { } else if (['vscode-insiders', 'code-oss'].includes(vscode.env.uriScheme)) {
prompt.then(item => { // Prompt after a single restart
if (item?.id === MessageAction.reportIssue) { if (!this._isPromptingAfterCrash && previousState.type === ServerState.Type.Errored && previousState.error instanceof TypeScriptServerError) {
const args = previousState.type === ServerState.Type.Errored && previousState.error instanceof TypeScriptServerError this.numberRestarts = 0;
? getReportIssueArgsForError(previousState.error) this._isPromptingAfterCrash = true;
: undefined; prompt = vscode.window.showWarningMessage(
return vscode.commands.executeCommand('workbench.action.openIssueReporter', args); localize('serverDiedOnce', 'The TypeScript language service died unexpectedly.'),
} reportIssueItem);
return undefined;
});
} }
} }
prompt?.then(item => {
this._isPromptingAfterCrash = false;
if (item === reportIssueItem) {
const args = previousState.type === ServerState.Type.Errored && previousState.error instanceof TypeScriptServerError
? getReportIssueArgsForError(previousState.error)
: undefined;
vscode.commands.executeCommand('workbench.action.openIssueReporter', args);
}
});
if (startService) { if (startService) {
this.startService(true); this.startService(true);
} }