diff --git a/_extension/src/session.ts b/_extension/src/session.ts index 6bb76a1cf0..1db9398dbf 100644 --- a/_extension/src/session.ts +++ b/_extension/src/session.ts @@ -25,6 +25,8 @@ export class SessionManager implements vscode.Disposable { private traceOutputChannel: vscode.LogOutputChannel; private initializedEventEmitter: vscode.EventEmitter; private telemetryReporter: TelemetryReporter; + private restartCount: number = 0; + private restartPromptShown: boolean = false; constructor( context: vscode.ExtensionContext, @@ -43,12 +45,41 @@ export class SessionManager implements vscode.Disposable { registerCommands(context: vscode.ExtensionContext): void { this.disposables.push(vscode.commands.registerCommand("typescript.native-preview.restart", async () => { this.telemetryReporter.sendTelemetryEvent("command.restartLanguageServer"); - if (await this.currentSession?.tryRestartClient(context)) { - // Language client was able to restart without a full session restart - return; + + // Most of the time we can restart the client without fully restarting the session. + const clientRestarted = await this.currentSession?.tryRestartClient(context); + if (!clientRestarted) { + await this.restart(context); } - await this.restart(context); + this.restartCount++; + if (this.restartCount >= 5 && !this.restartPromptShown) { + this.restartPromptShown = true; + this.telemetryReporter.sendTelemetryEvent("restartExceeded.warningShown"); + const experiencing = await vscode.window.showWarningMessage( + "You've restarted the language server several times. Are you experiencing an issue?", + "Yes", + "No", + ) ?? "Dismiss"; + + this.telemetryReporter.sendTelemetryEvent("restartExceeded.experiencingIssue", { choice: experiencing }); + if (experiencing === "Yes") { + const action = await vscode.window.showWarningMessage( + "Would you like to report the issue or view the server output?", + "Report Issue", + "Show Output Logs", + "Dismiss", + ) ?? "Dismiss"; + + this.telemetryReporter.sendTelemetryEvent("restartExceeded.action", { choice: action }); + if (action === "Report Issue") { + vscode.commands.executeCommand("typescript.native-preview.reportIssue"); + } + else if (action === "Show Output Logs") { + vscode.commands.executeCommand("typescript.native-preview.output.focus"); + } + } + } })); } diff --git a/_extension/src/telemetryReporting.ts b/_extension/src/telemetryReporting.ts index 1fcd165205..b76d484ac9 100644 --- a/_extension/src/telemetryReporting.ts +++ b/_extension/src/telemetryReporting.ts @@ -15,6 +15,9 @@ export interface TelemetryReporter { sendTelemetryEvent(eventName: "command.disableNativePreview"): void; sendTelemetryEvent(eventName: "command.restartLanguageServer"): void; sendTelemetryEvent(eventName: "command.reportIssue"): void; + sendTelemetryEvent(eventName: "restartExceeded.warningShown"): void; + sendTelemetryEvent(eventName: "restartExceeded.experiencingIssue", data: RestartExceededExperiencingIssue): void; + sendTelemetryEvent(eventName: "restartExceeded.action", data: RestartExceededAction): void; sendTelemetryEvent(eventName: "languageServer.start", data: LSServerStart): void; sendTelemetryErrorEvent(eventName: "languageServer.connectionError", data: LSConnectionError): void; @@ -100,3 +103,11 @@ export type ReportIssue = {}; export type UnexpectedTelemetryPurpose = { telemetryPurpose: string; }; + +export type RestartExceededExperiencingIssue = { + choice: "Yes" | "No" | "Dismiss"; +}; + +export type RestartExceededAction = { + choice: "Report Issue" | "Show Output Logs" | "Dismiss"; +};