From c0df26be420a5f0702214c393d85577843227437 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Sat, 27 Jul 2024 21:43:35 -0700 Subject: [PATCH 1/2] feat: use vscode log format for client logs This change updates the log format to use the vscode log format instead of the custom log format, by replacing the `OutputChannel` with a `LogOutputChannel` and using the `debug`, `info`, `warn`, and `error` methods on it. This has the following benefits: - Each log level now has its own color and the timestamp is in a more standard format - Inspect output (e.g. the log of the config object) is now colored - Error stack traces are now shown in the output - The log level is now controlled on the output tab by clicking the gear icon and selecting "Debug" or by passing the `--log` parameter to vscode. The `trace.extension` setting has been marked as deprecated. --- src/tools/rust-analyzer/.vscode/launch.json | 12 ++-- .../rust-analyzer/editors/code/package.json | 1 + .../editors/code/src/bootstrap.ts | 8 ++- .../rust-analyzer/editors/code/src/config.ts | 5 -- .../rust-analyzer/editors/code/src/ctx.ts | 3 +- .../rust-analyzer/editors/code/src/util.ts | 61 +++++++++---------- 6 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/tools/rust-analyzer/.vscode/launch.json b/src/tools/rust-analyzer/.vscode/launch.json index c353737a35a8..e83c03796a4b 100644 --- a/src/tools/rust-analyzer/.vscode/launch.json +++ b/src/tools/rust-analyzer/.vscode/launch.json @@ -18,7 +18,8 @@ "args": [ // "--user-data-dir=${workspaceFolder}/target/code", "--disable-extensions", - "--extensionDevelopmentPath=${workspaceFolder}/editors/code" + "--extensionDevelopmentPath=${workspaceFolder}/editors/code", + "--log rust-lang.rust-analyzer:debug" ], "outFiles": [ "${workspaceFolder}/editors/code/out/**/*.js" @@ -36,7 +37,8 @@ "runtimeExecutable": "${execPath}", "args": [ "--disable-extensions", - "--extensionDevelopmentPath=${workspaceFolder}/editors/code" + "--extensionDevelopmentPath=${workspaceFolder}/editors/code", + "--log rust-lang.rust-analyzer:debug" ], "outFiles": [ "${workspaceFolder}/editors/code/out/**/*.js" @@ -57,7 +59,8 @@ "runtimeExecutable": "${execPath}", "args": [ "--disable-extensions", - "--extensionDevelopmentPath=${workspaceFolder}/editors/code" + "--extensionDevelopmentPath=${workspaceFolder}/editors/code", + "--log rust-lang.rust-analyzer:debug" ], "outFiles": [ "${workspaceFolder}/editors/code/out/**/*.js" @@ -79,7 +82,8 @@ "runtimeExecutable": "${execPath}", "args": [ "--disable-extension", "rust-lang.rust-analyzer", - "--extensionDevelopmentPath=${workspaceFolder}/editors/code" + "--extensionDevelopmentPath=${workspaceFolder}/editors/code", + "--log rust-lang.rust-analyzer:debug" ], "outFiles": [ "${workspaceFolder}/editors/code/out/**/*.js" diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 49defa5deae1..da06f133d03b 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -483,6 +483,7 @@ }, "rust-analyzer.trace.extension": { "description": "Enable logging of VS Code extensions itself.", + "markdownDeprecationMessage": "Log level is now controlled by the [Developer: Set Log Level...](command:workbench.action.setLogLevel) command.You can set the log level for the current session and also the default log level from there. This is also available by clicking the gear icon on the OUTPUT tab when Rust Analyzer Client is visible or by passing the --log rust-lang.rust-analyzer:debug parameter to VS Code.", "type": "boolean", "default": false } diff --git a/src/tools/rust-analyzer/editors/code/src/bootstrap.ts b/src/tools/rust-analyzer/editors/code/src/bootstrap.ts index 527edf19eb45..42dd0760d623 100644 --- a/src/tools/rust-analyzer/editors/code/src/bootstrap.ts +++ b/src/tools/rust-analyzer/editors/code/src/bootstrap.ts @@ -117,9 +117,11 @@ export function isValidExecutable(path: string, extraEnv: Env): boolean { env: { ...process.env, ...extraEnv }, }); - const printOutput = res.error ? log.warn : log.info; - printOutput(path, "--version:", res); - + if (res.error) { + log.warn(path, "--version:", res); + } else { + log.info(path, "--version:", res); + } return res.status === 0; } diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts index 75fbcdacae47..dc0165df71ea 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -41,7 +41,6 @@ export class Config { } private refreshLogging() { - log.setEnabled(this.traceExtension ?? false); log.info( "Extension version:", vscode.extensions.getExtension(this.extensionId)!.packageJSON.version, @@ -253,10 +252,6 @@ export class Config { await this.cfg.update("checkOnSave", !(value || false), target || null, overrideInLanguage); } - get traceExtension() { - return this.get("trace.extension"); - } - get discoverProjectRunner(): string | undefined { return this.get("discoverProjectRunner"); } diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts index 49e002627d87..0f2a758db427 100644 --- a/src/tools/rust-analyzer/editors/code/src/ctx.ts +++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts @@ -249,7 +249,8 @@ export class Ctx implements RustAnalyzerExtensionApi { message += 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). '; - message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }'; + message += + 'To enable verbose logs, click the gear icon in the "OUTPUT" tab and select "Debug".'; log.error("Bootstrap error", err); throw new Error(message); diff --git a/src/tools/rust-analyzer/editors/code/src/util.ts b/src/tools/rust-analyzer/editors/code/src/util.ts index dd1cbe38ff99..eb98425abff0 100644 --- a/src/tools/rust-analyzer/editors/code/src/util.ts +++ b/src/tools/rust-analyzer/editors/code/src/util.ts @@ -17,49 +17,44 @@ export type Env = { [name: string]: string; }; -export const log = new (class { - private enabled = true; - private readonly output = vscode.window.createOutputChannel("Rust Analyzer Client"); +class Log { + private readonly output = vscode.window.createOutputChannel("Rust Analyzer Client", { + log: true, + }); - setEnabled(yes: boolean): void { - log.enabled = yes; + debug(...messages: [unknown, ...unknown[]]): void { + this.output.debug(this.stringify(messages)); } - // Hint: the type [T, ...T[]] means a non-empty array - debug(...msg: [unknown, ...unknown[]]): void { - if (!log.enabled) return; - log.write("DEBUG", ...msg); + info(...messages: [unknown, ...unknown[]]): void { + this.output.info(this.stringify(messages)); } - info(...msg: [unknown, ...unknown[]]): void { - log.write("INFO", ...msg); + warn(...messages: [unknown, ...unknown[]]): void { + this.output.warn(this.stringify(messages)); } - warn(...msg: [unknown, ...unknown[]]): void { - debugger; - log.write("WARN", ...msg); + error(...messages: [unknown, ...unknown[]]): void { + this.output.error(this.stringify(messages)); + this.output.show(true); } - error(...msg: [unknown, ...unknown[]]): void { - debugger; - log.write("ERROR", ...msg); - log.output.show(true); + private stringify(messages: unknown[]): string { + return messages + .map((message) => { + if (typeof message === "string") { + return message; + } + if (message instanceof Error) { + return message.stack || message.message; + } + return inspect(message, { depth: 6, colors: false }); + }) + .join(" "); } +} - private write(label: string, ...messageParts: unknown[]): void { - const message = messageParts.map(log.stringify).join(" "); - const dateTime = new Date().toLocaleString(); - log.output.appendLine(`${label} [${dateTime}]: ${message}`); - } - - private stringify(val: unknown): string { - if (typeof val === "string") return val; - return inspect(val, { - colors: false, - depth: 6, // heuristic - }); - } -})(); +export const log = new Log(); export function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); @@ -135,7 +130,7 @@ export function execute(command: string, options: ExecOptions): Promise return new Promise((resolve, reject) => { exec(command, options, (err, stdout, stderr) => { if (err) { - log.error(err); + log.error("error:", err); reject(err); return; } From 2f0451d113bd807a8d10ab667346f3fa77062632 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Sat, 27 Jul 2024 21:59:12 -0700 Subject: [PATCH 2/2] feat: add trace level to client logs --- src/tools/rust-analyzer/editors/code/src/util.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/rust-analyzer/editors/code/src/util.ts b/src/tools/rust-analyzer/editors/code/src/util.ts index eb98425abff0..db64a013fda3 100644 --- a/src/tools/rust-analyzer/editors/code/src/util.ts +++ b/src/tools/rust-analyzer/editors/code/src/util.ts @@ -22,6 +22,10 @@ class Log { log: true, }); + trace(...messages: [unknown, ...unknown[]]): void { + this.output.trace(this.stringify(messages)); + } + debug(...messages: [unknown, ...unknown[]]): void { this.output.debug(this.stringify(messages)); }