Skip to content

Commit c61baaf

Browse files
stamblerrehyangah
authored andcommitted
[release] goLanguageServer: track language server's restart history
And show it in automated issue reports. This will allow us to see if crashes were potentially caused by a bad restart. Sometimes we notice crashes that don't have any associated gopls stack traces, so we were wondering if there is something about the way that we do restarts that causes these issues. Automated issues will list when and why the language server was restarted, as well as when the issue was suggested. Change-Id: I298cb4a4931bfedeb75bada446ddbc480eec1501 Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/348973 Reviewed-by: Hyang-Ah Hana Kim <[email protected]> Trust: Hyang-Ah Hana Kim <[email protected]> Trust: Rebecca Stambler <[email protected]> Run-TryBot: Hyang-Ah Hana Kim <[email protected]> TryBot-Result: kokoro <[email protected]> (cherry picked from commit c71634c) Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/350139 Reviewed-by: Rebecca Stambler <[email protected]>
1 parent 3c8da71 commit c61baaf

File tree

3 files changed

+48
-18
lines changed

3 files changed

+48
-18
lines changed

src/goInstallTools.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {
3434
getBinPath,
3535
getBinPathWithExplanation,
3636
getCheckForToolsUpdatesConfig,
37-
getCurrentGoPath,
3837
getGoVersion,
3938
getTempFilePath,
4039
getWorkspaceFolderPath,
@@ -44,7 +43,7 @@ import {
4443
import { correctBinname, envPath, getCurrentGoRoot, setCurrentGoRoot } from './utils/pathUtils';
4544
import util = require('util');
4645
import vscode = require('vscode');
47-
import { isInPreviewMode } from './goLanguageServer';
46+
import { isInPreviewMode, RestartReason } from './goLanguageServer';
4847

4948
// declinedUpdates tracks the tools that the user has declined to update.
5049
const declinedUpdates: Tool[] = [];
@@ -174,7 +173,7 @@ export async function installTools(
174173
if (result.reason === '') {
175174
// Restart the language server if a new binary has been installed.
176175
if (result.tool.name === 'gopls') {
177-
restartLanguageServer();
176+
restartLanguageServer('installation');
178177
}
179178
} else {
180179
failures.push(result);

src/goLanguageServer.ts

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,37 @@ let serverTraceChannel: vscode.OutputChannel;
105105
let crashCount = 0;
106106

107107
// Some metrics for automated issue reports:
108-
let manualRestartCount = 0;
109-
let totalStartCount = 0;
108+
let restartHistory: Restart[] = [];
109+
110+
export function updateRestartHistory(reason: RestartReason, enabled: boolean) {
111+
// Keep the history limited to 10 elements.
112+
while (restartHistory.length > 10) {
113+
restartHistory = restartHistory.slice(1);
114+
}
115+
restartHistory.push(new Restart(reason, new Date(), enabled));
116+
}
117+
118+
function formatRestartHistory(): string {
119+
const result: string[] = [];
120+
for (const restart of restartHistory) {
121+
result.push(`${restart.timestamp.toUTCString()}: ${restart.reason} (enabled: ${restart.enabled})`);
122+
}
123+
return result.join('\n');
124+
}
125+
126+
export type RestartReason = 'activation' | 'manual' | 'config change' | 'installation';
127+
128+
class Restart {
129+
reason: RestartReason;
130+
timestamp: Date;
131+
enabled: boolean;
132+
133+
constructor(reason: RestartReason, timestamp: Date, enabled: boolean) {
134+
this.reason = reason;
135+
this.timestamp = timestamp;
136+
this.enabled = enabled;
137+
}
138+
}
110139

111140
// defaultLanguageProviders is the list of providers currently registered.
112141
let defaultLanguageProviders: vscode.Disposable[] = [];
@@ -121,7 +150,7 @@ export let lastUserAction: Date = new Date();
121150

122151
// startLanguageServerWithFallback starts the language server, if enabled,
123152
// or falls back to the default language providers.
124-
export async function startLanguageServerWithFallback(ctx: vscode.ExtensionContext, activation: boolean) {
153+
export async function startLanguageServerWithFallback(ctx: vscode.ExtensionContext, reason: RestartReason) {
125154
for (const folder of vscode.workspace.workspaceFolders || []) {
126155
switch (folder.uri.scheme) {
127156
case 'vsls':
@@ -148,9 +177,11 @@ export async function startLanguageServerWithFallback(ctx: vscode.ExtensionConte
148177
const goConfig = getGoConfig();
149178
const cfg = buildLanguageServerConfig(goConfig);
150179

180+
updateRestartHistory(reason, cfg.enabled);
181+
151182
// We have some extra prompts for gopls users and for people who have opted
152183
// out of gopls.
153-
if (activation) {
184+
if (reason === 'activation') {
154185
scheduleGoplsSuggestions();
155186
}
156187

@@ -406,9 +437,7 @@ async function startLanguageServer(ctx: vscode.ExtensionContext, config: Languag
406437
"Looks like you're about to manually restart the language server.",
407438
errorKind.manualRestart
408439
);
409-
410-
manualRestartCount++;
411-
restartLanguageServer();
440+
restartLanguageServer('manual');
412441
});
413442
ctx.subscriptions.push(restartCommand);
414443
}
@@ -418,7 +447,6 @@ async function startLanguageServer(ctx: vscode.ExtensionContext, config: Languag
418447
disposeDefaultProviders();
419448

420449
languageServerDisposable = languageClient.start();
421-
totalStartCount++;
422450
ctx.subscriptions.push(languageServerDisposable);
423451
await languageClient.onReady();
424452
return true;
@@ -922,7 +950,7 @@ export async function watchLanguageServerConfiguration(e: vscode.ConfigurationCh
922950
e.affectsConfiguration('go.formatTool')
923951
// TODO: Should we check http.proxy too? That affects toolExecutionEnvironment too.
924952
) {
925-
restartLanguageServer();
953+
restartLanguageServer('config change');
926954
}
927955

928956
if (e.affectsConfiguration('go.useLanguageServer') && getGoConfig()['useLanguageServer'] === false) {
@@ -1384,6 +1412,7 @@ Please copy the stack trace and error messages from that window and paste it in
13841412
13851413
Failed to auto-collect gopls trace: ${failureReason}.
13861414
`;
1415+
const now = new Date();
13871416

13881417
const body = `
13891418
gopls version: ${usersGoplsVersion}
@@ -1393,8 +1422,9 @@ extension version: ${extInfo.version}
13931422
go version: ${goVersion?.format(true)}
13941423
environment: ${extInfo.appName} ${process.platform}
13951424
initialization error: ${initializationError}
1396-
manual restart count: ${manualRestartCount}
1397-
total start count: ${totalStartCount}
1425+
issue timestamp: ${now.toUTCString()}
1426+
restart history:
1427+
${formatRestartHistory()}
13981428
13991429
ATTENTION: PLEASE PROVIDE THE DETAILS REQUESTED BELOW.
14001430

src/goMain.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
import {
4848
isInPreviewMode,
4949
languageServerIsRunning,
50+
RestartReason,
5051
showServerOutputChannel,
5152
startLanguageServerWithFallback,
5253
watchLanguageServerConfiguration
@@ -124,7 +125,7 @@ export let vetDiagnosticCollection: vscode.DiagnosticCollection;
124125
// restartLanguageServer wraps all of the logic needed to restart the
125126
// language server. It can be used to enable, disable, or otherwise change
126127
// the configuration of the server.
127-
export let restartLanguageServer = () => {
128+
export let restartLanguageServer = (reason: RestartReason) => {
128129
return;
129130
};
130131

@@ -887,12 +888,12 @@ function configureLanguageServer(ctx: vscode.ExtensionContext) {
887888
// Set the function that is used to restart the language server.
888889
// This is necessary, even if the language server is not currently
889890
// in use.
890-
restartLanguageServer = async () => {
891-
startLanguageServerWithFallback(ctx, false);
891+
restartLanguageServer = async (reason: RestartReason) => {
892+
startLanguageServerWithFallback(ctx, reason);
892893
};
893894

894895
// Start the language server, or fallback to the default language providers.
895-
return startLanguageServerWithFallback(ctx, true);
896+
return startLanguageServerWithFallback(ctx, 'activation');
896897
}
897898

898899
function getCurrentGoPathCommand() {

0 commit comments

Comments
 (0)