Skip to content

Commit a671ba3

Browse files
hyangahgopherbot
authored andcommitted
extension: replace src/goLogging with vscode LogOutputChannel API
goLogging was used for extension's verbose/debug logging and debug session's client-side logging ("Go Debug") output channel. vscode's LogOutputChannel API provides log level control consistent across all VS Code components. More importantly, this allows users to inspect verbose/debug level logging messages from the Go output channel easily, instead of relying on the Developer's debug console (which is not guaranteed to be accessible from non-desktop editor integration products). Convert the "Go Debug" output channel to vscode LogOutputChannel. This allows us to control the logging level separate from the shared go.logging.level configuration. In fact, 'go.logging.level' setting is no longer necessary. Mark it deprecated. Change-Id: I4180eb1ce8afee63863d741b3501f0624aa42433 Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/559739 TryBot-Result: kokoro <[email protected]> Reviewed-by: Suzy Mueller <[email protected]> Auto-Submit: Hyang-Ah Hana Kim <[email protected]> Commit-Queue: Hyang-Ah Hana Kim <[email protected]>
1 parent 66a896f commit a671ba3

File tree

11 files changed

+67
-231
lines changed

11 files changed

+67
-231
lines changed

docs/settings.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,10 @@ Specifies Lint tool name.<br/>
345345
Allowed Options: `staticcheck`, `golint`, `golangci-lint`, `revive`
346346

347347
Default: `"staticcheck"`
348-
### `go.logging.level`
348+
### `go.logging.level (deprecated)`
349349

350-
The logging level the extension logs at, defaults to 'error'<br/>
351-
Allowed Options: `off`, `error`, `info`, `verbose`
350+
This setting is deprecated. Use 'Developer: Set Log Level...' command to control logging level instead.
352351

353-
Default: `"error"`
354352
### `go.playground`
355353

356354
The flags configured here will be passed through to command `goplay`

extension/package.json

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,14 +1514,7 @@
15141514
},
15151515
"go.logging.level": {
15161516
"type": "string",
1517-
"default": "error",
1518-
"enum": [
1519-
"off",
1520-
"error",
1521-
"info",
1522-
"verbose"
1523-
],
1524-
"description": "The logging level the extension logs at, defaults to 'error'",
1517+
"deprecationMessage": "This setting is deprecated. Use 'Developer: Set Log Level...' command to control logging level instead.",
15251518
"scope": "machine-overridable"
15261519
},
15271520
"go.toolsManagement.go": {

extension/src/goDebugFactory.ts

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@ import getPort = require('get-port');
1212
import path = require('path');
1313
import * as fs from 'fs';
1414
import * as net from 'net';
15-
import { Logger, logVerbose, TimestampedLogger } from './goLogging';
1615
import { DebugProtocol } from 'vscode-debugprotocol';
1716
import { getWorkspaceFolderPath } from './util';
1817
import { getEnvPath, getBinPathFromEnvVar } from './utils/pathUtils';
1918
import { GoExtensionContext } from './context';
2019
import { createRegisterCommand } from './commands';
2120

2221
export function activate(ctx: vscode.ExtensionContext, goCtx: GoExtensionContext) {
23-
const debugOutputChannel = vscode.window.createOutputChannel('Go Debug');
22+
const debugOutputChannel = vscode.window.createOutputChannel('Go Debug', { log: true });
2423
ctx.subscriptions.push(debugOutputChannel);
2524

2625
const factory = new GoDebugAdapterDescriptorFactory(debugOutputChannel);
@@ -40,7 +39,7 @@ export function activate(ctx: vscode.ExtensionContext, goCtx: GoExtensionContext
4039
}
4140

4241
class GoDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
43-
constructor(private outputChannel?: vscode.OutputChannel) {}
42+
constructor(private outputChannel: vscode.LogOutputChannel) {}
4443

4544
public createDebugAdapterDescriptor(
4645
session: vscode.DebugSession,
@@ -59,11 +58,11 @@ class GoDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFa
5958
private async createDebugAdapterDescriptorDlvDap(
6059
configuration: vscode.DebugConfiguration
6160
): Promise<vscode.ProviderResult<vscode.DebugAdapterDescriptor>> {
62-
const logger = new TimestampedLogger(configuration.trace, this.outputChannel);
63-
logger.debug(`Config: ${JSON.stringify(configuration)}\n`);
61+
const logger = this.outputChannel;
62+
logger.debug(`Config: ${JSON.stringify(configuration)}`);
6463
if (configuration.port) {
6564
const host = configuration.host ?? '127.0.0.1';
66-
logger.info(`Connecting to DAP server at ${host}:${configuration.port}\n`);
65+
logger.info(`Connecting to DAP server at ${host}:${configuration.port}`);
6766
return new vscode.DebugAdapterServer(configuration.port, host);
6867
}
6968
const d = new DelveDAPOutputAdapter(configuration, logger);
@@ -72,28 +71,24 @@ class GoDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFa
7271
}
7372

7473
class GoDebugAdapterTrackerFactory implements vscode.DebugAdapterTrackerFactory {
75-
constructor(private outputChannel: vscode.OutputChannel) {}
74+
constructor(private outputChannel: vscode.LogOutputChannel) {}
7675

7776
createDebugAdapterTracker(session: vscode.DebugSession) {
78-
const level = session.configuration?.trace;
79-
if (!level || level === 'off') {
80-
return null;
81-
}
82-
const logger = new TimestampedLogger(session.configuration?.trace || 'off', this.outputChannel);
77+
const logger = this.outputChannel;
8378
let requestsSent = 0;
8479
let responsesReceived = 0;
8580
return {
8681
onWillStartSession: () =>
87-
logger.debug(`session ${session.id} will start with ${JSON.stringify(session.configuration)}\n`),
82+
logger.debug(`session ${session.id} will start with ${JSON.stringify(session.configuration)}`),
8883
onWillReceiveMessage: (message: any) => {
89-
logger.trace(`client -> ${JSON.stringify(message)}\n`);
84+
logger.trace(`client -> ${JSON.stringify(message)}`);
9085
requestsSent++;
9186
},
9287
onDidSendMessage: (message: any) => {
93-
logger.trace(`client <- ${JSON.stringify(message)}\n`);
88+
logger.trace(`client <- ${JSON.stringify(message)}`);
9489
responsesReceived++;
9590
},
96-
onError: (error: Error) => logger.error(`error: ${error}\n`),
91+
onError: (error: Error) => logger.error(`error: ${error}`),
9792
onWillStopSession: () => {
9893
if (
9994
session.configuration.debugAdapter === 'dlv-dap' &&
@@ -109,7 +104,7 @@ class GoDebugAdapterTrackerFactory implements vscode.DebugAdapterTrackerFactory
109104
logger.debug(`session ${session.id} will stop\n`);
110105
},
111106
onExit: (code: number | undefined, signal: string | undefined) =>
112-
logger.info(`debug adapter exited: (code: ${code}, signal: ${signal})\n`)
107+
logger.info(`debug adapter exited: (code: ${code}, signal: ${signal})`)
113108
};
114109
}
115110

@@ -118,6 +113,8 @@ class GoDebugAdapterTrackerFactory implements vscode.DebugAdapterTrackerFactory
118113

119114
const TWO_CRLF = '\r\n\r\n';
120115

116+
type ILogger = Pick<vscode.LogOutputChannel, 'error' | 'info' | 'debug' | 'trace'>;
117+
121118
// Proxies DebugProtocolMessage exchanges between VSCode and a remote
122119
// process or server connected through a duplex stream, after its
123120
// start method is called.
@@ -126,10 +123,10 @@ export class ProxyDebugAdapter implements vscode.DebugAdapter {
126123
// connection from/to server (= dlv dap)
127124
private readable?: stream.Readable;
128125
private writable?: stream.Writable;
129-
protected logger?: Logger;
126+
protected logger: ILogger;
130127
private terminated = false;
131128

132-
constructor(logger: Logger) {
129+
constructor(logger: ILogger) {
133130
this.logger = logger;
134131
this.onDidSendMessage = this.messageEmitter.event;
135132
}
@@ -240,7 +237,7 @@ export class ProxyDebugAdapter implements vscode.DebugAdapter {
240237
// VSCode and a dlv dap process spawned and managed by this adapter.
241238
// It turns the process's stdout/stderrr into OutputEvent.
242239
export class DelveDAPOutputAdapter extends ProxyDebugAdapter {
243-
constructor(private configuration: vscode.DebugConfiguration, logger: Logger) {
240+
constructor(private configuration: vscode.DebugConfiguration, logger: ILogger) {
244241
super(logger);
245242
}
246243

@@ -252,7 +249,7 @@ export class DelveDAPOutputAdapter extends ProxyDebugAdapter {
252249
protected sendMessageToClient(message: vscode.DebugProtocolMessage) {
253250
const m = message as any;
254251
if (m.type === 'request') {
255-
logVerbose(`do not forward reverse request: dropping ${JSON.stringify(m)}`);
252+
this.logger.debug(`do not forward reverse request: dropping ${JSON.stringify(m)}`);
256253
return;
257254
}
258255

@@ -262,7 +259,7 @@ export class DelveDAPOutputAdapter extends ProxyDebugAdapter {
262259
protected async sendMessageToServer(message: vscode.DebugProtocolMessage): Promise<void> {
263260
const m = message as any;
264261
if (m.type === 'response') {
265-
logVerbose(`do not forward reverse request response: dropping ${JSON.stringify(m)}`);
262+
this.logger.debug(`do not forward reverse request response: dropping ${JSON.stringify(m)}`);
266263
return;
267264
}
268265

@@ -353,7 +350,7 @@ export class DelveDAPOutputAdapter extends ProxyDebugAdapter {
353350
} catch (err) {
354351
return { connected: false, reason: err };
355352
}
356-
this.logger?.debug(`Running dlv dap server: pid=${this.dlvDapServer?.pid}\n`);
353+
this.logger?.debug(`Running dlv dap server: pid=${this.dlvDapServer?.pid}`);
357354
return { connected: true };
358355
}
359356

@@ -372,7 +369,7 @@ export class DelveDAPOutputAdapter extends ProxyDebugAdapter {
372369
// may not appear in the DEBUG CONSOLE. For easier debugging, log
373370
// the messages through the logger that prints to Go Debug output
374371
// channel.
375-
this.logger?.info(msg);
372+
this.logger?.trace(msg);
376373
};
377374

378375
// If a port has been specified, assume there is an already
@@ -437,7 +434,7 @@ export class DelveDAPOutputAdapter extends ProxyDebugAdapter {
437434

438435
try {
439436
const port = await getPort();
440-
const rendezvousServerPromise = waitForDAPServer(port, 30_000);
437+
const rendezvousServerPromise = waitForDAPServer(port, 30_000, this.logger);
441438

442439
dlvArgs.push(`--client-addr=:${port}`);
443440

@@ -470,7 +467,7 @@ function getSudo(): string | null {
470467
return sudoPath;
471468
}
472469

473-
function waitForDAPServer(port: number, timeoutMs: number): Promise<net.Socket> {
470+
function waitForDAPServer(port: number, timeoutMs: number, logger: ILogger): Promise<net.Socket> {
474471
return new Promise((resolve, reject) => {
475472
// eslint-disable-next-line prefer-const
476473
let s: net.Server | undefined;
@@ -482,7 +479,7 @@ function waitForDAPServer(port: number, timeoutMs: number): Promise<net.Socket>
482479
}, timeoutMs);
483480

484481
s = net.createServer({ pauseOnConnect: true }, (socket) => {
485-
logVerbose(
482+
logger.debug(
486483
`connected: ${port} (remote: ${socket.remoteAddress}:${socket.remotePort} local: ${socket.localAddress}:${socket.localPort})`
487484
);
488485
clearTimeout(timeoutToken);
@@ -491,7 +488,7 @@ function waitForDAPServer(port: number, timeoutMs: number): Promise<net.Socket>
491488
resolve(socket);
492489
});
493490
s.on('error', (err) => {
494-
logVerbose(`connection error ${err}`);
491+
logger.error(`connection error ${err}`);
495492
reject(err);
496493
});
497494
s.maxConnections = 1;

extension/src/goEnv.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import vscode = require('vscode');
99
import { getGoConfig } from './config';
1010
import { getCurrentGoPath, getToolsGopath, resolvePath, substituteEnv } from './util';
11-
import { logVerbose } from './goLogging';
1211
import { dirExists } from './utils/pathUtils';
1312
import { getFromGlobalState, updateGlobalState } from './stateUtils';
13+
import { outputChannel } from './goStatus';
1414

1515
// toolInstallationEnvironment returns the environment in which tools should
1616
// be installed. It always returns a new object.
@@ -67,7 +67,7 @@ export function toolExecutionEnvironment(uri?: vscode.Uri, addProcessEnv = true)
6767
// Remove json flag (-json or --json=<any>) from GOFLAGS because it will effect to result format of the execution
6868
if (env['GOFLAGS'] && env['GOFLAGS'].includes('-json')) {
6969
env['GOFLAGS'] = env['GOFLAGS'].replace(/(^|\s+)-?-json[^\s]*/g, '');
70-
logVerbose(`removed -json from GOFLAGS: ${env['GOFLAGS']}`);
70+
outputChannel.debug(`removed -json from GOFLAGS: ${env['GOFLAGS']}`);
7171
}
7272
return env;
7373
}
@@ -127,7 +127,9 @@ export async function setGOROOTEnvVar(configGOROOT: string) {
127127
});
128128
}
129129

130-
logVerbose(`setting GOROOT = ${goroot} (old value: ${currentGOROOT}) because "go.goroot": "${configGOROOT}"`);
130+
outputChannel.debug(
131+
`setting GOROOT = ${goroot} (old value: ${currentGOROOT}) because "go.goroot": "${configGOROOT}"`
132+
);
131133
if (goroot) {
132134
process.env['GOROOT'] = goroot;
133135
} else {

extension/src/goEnvironmentStatus.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import path = require('path');
1515
import { promisify } from 'util';
1616
import { getGoConfig, extensionInfo } from './config';
1717
import { toolInstallationEnvironment } from './goEnv';
18-
import { logVerbose } from './goLogging';
1918
import { addGoStatus, goEnvStatusbarItem, outputChannel, removeGoStatus } from './goStatus';
2019
import { getFromGlobalState, getFromWorkspaceState, updateGlobalState, updateWorkspaceState } from './stateUtils';
2120
import { getBinPath, getCheckForToolsUpdatesConfig, getGoVersion, GoVersion } from './util';
@@ -295,7 +294,7 @@ export function addGoRuntimeBaseToPATH(newGoRuntimeBase: string) {
295294
}
296295
const pathEnvVar = pathEnvVarName();
297296
if (!pathEnvVar) {
298-
logVerbose("couldn't find PATH property in process.env");
297+
outputChannel.debug("couldn't find PATH property in process.env");
299298
return;
300299
}
301300

@@ -304,7 +303,7 @@ export function addGoRuntimeBaseToPATH(newGoRuntimeBase: string) {
304303
defaultPathEnv = <string>process.env[pathEnvVar];
305304
}
306305

307-
logVerbose(`addGoRuntimeBase(${newGoRuntimeBase}) when PATH=${defaultPathEnv}`);
306+
outputChannel.debug(`addGoRuntimeBase(${newGoRuntimeBase}) when PATH=${defaultPathEnv}`);
308307

309308
// calling this multiple times will override the previous value.
310309
// environmentVariableCollection.clear();
@@ -354,7 +353,7 @@ export function clearGoRuntimeBaseFromPATH() {
354353
}
355354
const pathEnvVar = pathEnvVarName();
356355
if (!pathEnvVar) {
357-
logVerbose("couldn't find PATH property in process.env");
356+
outputChannel.debug("couldn't find PATH property in process.env");
358357
return;
359358
}
360359
environmentVariableCollection?.delete(pathEnvVar);

extension/src/goInstallTools.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import { ConfigurationTarget } from 'vscode';
1616
import { extensionInfo, getGoConfig, getGoplsConfig } from './config';
1717
import { toolExecutionEnvironment, toolInstallationEnvironment } from './goEnv';
1818
import { addGoRuntimeBaseToPATH, clearGoRuntimeBaseFromPATH } from './goEnvironmentStatus';
19-
import { logVerbose, logError } from './goLogging';
2019
import { GoExtensionContext } from './context';
2120
import { addGoStatus, initGoStatusBar, outputChannel, removeGoStatus } from './goStatus';
2221
import { containsTool, getConfiguredTools, getImportPathWithVersion, getTool, Tool, ToolAtVersion } from './goTools';
@@ -109,22 +108,19 @@ export async function installAllTools(updateExistingToolsOnly = false) {
109108
async function getGoForInstall(goVersion: GoVersion, silent?: boolean): Promise<GoVersion> {
110109
const configured = getGoConfig().get<string>('toolsManagement.go');
111110
if (!configured) {
112-
return goVersion;
111+
return goVersion; // use the default.
113112
}
114113

115114
try {
116115
const go = await getGoVersion(configured);
117116
if (go) return go;
118117
} catch (e) {
119-
logError(`getGoForInstall failed to run 'go version' with the configured go for tool install: ${e}`);
120-
} finally {
121118
if (!silent) {
122119
outputChannel.error(
123-
`Ignoring misconfigured 'go.toolsManagement.go' (${configured}). Provide a valid path to the Go command.`
120+
`failed to run "go version" with "${configured}". Provide a valid path to the Go binary`
124121
);
125122
}
126123
}
127-
128124
return goVersion;
129125
}
130126

@@ -152,7 +148,10 @@ export async function installTools(
152148
return [];
153149
}
154150
const { silent, skipRestartGopls } = options || {};
155-
outputChannel.appendLine('Installing tools...');
151+
if (!silent) {
152+
outputChannel.show();
153+
}
154+
outputChannel.clear();
156155

157156
const goForInstall = await getGoForInstall(goVersion);
158157

@@ -219,9 +218,9 @@ export async function installTools(
219218
if (silent) {
220219
outputChannel.show();
221220
}
222-
outputChannel.error(failures.length + ' tools failed to install.\n');
221+
outputChannel.appendLine(failures.length + ' tools failed to install.\n');
223222
for (const failure of failures) {
224-
outputChannel.error(`${failure.tool.name}: ${failure.reason} `);
223+
outputChannel.appendLine(`${failure.tool.name}: ${failure.reason} `);
225224
}
226225
}
227226
if (missing.some((tool) => tool.isImportant)) {
@@ -277,8 +276,8 @@ async function installToolWithGo(
277276
const toolInstallPath = getBinPath(tool.name);
278277
outputChannel.appendLine(`Installing ${importPath} (${toolInstallPath}) SUCCEEDED`);
279278
} catch (e) {
280-
outputChannel.error(`Installing ${importPath} FAILED`);
281-
outputChannel.error(`${JSON.stringify(e, null, 1)}`);
279+
outputChannel.appendLine(`Installing ${importPath} FAILED`);
280+
outputChannel.appendLine(`${JSON.stringify(e, null, 1)}`);
282281
return `failed to install ${tool.name}(${importPath}): ${e}`;
283282
}
284283
}
@@ -293,7 +292,7 @@ async function installToolWithGoInstall(goVersion: GoVersion, env: NodeJS.Dict<s
293292
};
294293

295294
const execFile = util.promisify(cp.execFile);
296-
logVerbose(`$ ${goBinary} install -v ${importPath}} (cwd: ${opts.cwd})`);
295+
outputChannel.trace(`$ ${goBinary} install -v ${importPath}} (cwd: ${opts.cwd})`);
297296
await execFile(goBinary, ['install', '-v', importPath], opts);
298297
}
299298

@@ -452,7 +451,7 @@ export function updateGoVarsFromConfig(goCtx: GoExtensionContext): Promise<void>
452451
const { binPath, why } = getBinPathWithExplanation('go', false);
453452
const goRuntimePath = binPath;
454453

455-
logVerbose(`updateGoVarsFromConfig: found 'go' in ${goRuntimePath}`);
454+
outputChannel.debug(`updateGoVarsFromConfig: found 'go' in ${goRuntimePath}`);
456455
if (!goRuntimePath || !path.isAbsolute(goRuntimePath)) {
457456
// getBinPath returns the absolute path to the tool if it exists.
458457
// Otherwise, it may return the tool name (e.g. 'go').
@@ -481,12 +480,13 @@ export function updateGoVarsFromConfig(goCtx: GoExtensionContext): Promise<void>
481480
if (stderr) {
482481
// 'go env' may output warnings about potential misconfiguration.
483482
// Show the messages to users but keep processing the stdout.
484-
outputChannel.error(`'${goRuntimePath} env': ${stderr}`);
483+
outputChannel.append(`'${goRuntimePath} env': ${stderr}`);
485484
outputChannel.show();
486485
}
487-
logVerbose(`${goRuntimePath} env ...:\n${stdout}`);
486+
outputChannel.trace(`${goRuntimePath} env ...:\n${stdout}`);
488487
const envOutput = JSON.parse(stdout);
489488
if (envOutput.GOROOT && envOutput.GOROOT.trim()) {
489+
outputChannel.debug('setCurrentGOROOT:', envOutput.GOROOT);
490490
setCurrentGoRoot(envOutput.GOROOT.trim());
491491
delete envOutput.GOROOT;
492492
}

0 commit comments

Comments
 (0)