Implement LogOutputWindow for Logging (#5065) · PowerShell/vscode-powershell@400fd75 · GitHub
Skip to content

Commit 400fd75

Browse files
authored
Implement LogOutputWindow for Logging (#5065)
* Implement LogOutputChannel and move settings to UI * Remove unnecessary comment * Remove File Logging (done by LogOutputWindow automatically) * First Connect * Add output adapters, LSP restart settings * Fix Log Uri Test * Forgot to add to extension facing API * Accidentally made a recursive rather than reference what I wanted to. Thanks Copilot... * Pre-Restart Experiments * Move Commands out of logger temporarily * Initial Cleanup of Logging, looks good ATM * Merge client and server editorservices logs * Add new MergedOutputChannel log * Remove unnecessary Import * Update settings for new EditorServicesLogLevels * Wire up loglevels in-band due to LSP bug * Rework multiple classes into a parser function injection * Fix some glyphs * Revert extra config settings for dynamic log configuration for now * Remove SetLSPTrace for now * Clean import * Align logging terminology to vscode output windows and remove editorServices from options definitions
1 parent 7126891 commit 400fd75

12 files changed

Lines changed: 422 additions & 245 deletions

File tree

‎docs/troubleshooting.md‎

Lines changed: 2 additions & 2 deletions

‎package.json‎

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -916,24 +916,24 @@
916916
},
917917
"powershell.developer.editorServicesLogLevel": {
918918
"type": "string",
919-
"default": "Normal",
919+
"default": "Warning",
920920
"enum": [
921-
"Diagnostic",
922-
"Verbose",
923-
"Normal",
921+
"Trace",
922+
"Debug",
923+
"Information",
924924
"Warning",
925925
"Error",
926926
"None"
927927
],
928928
"markdownEnumDescriptions": [
929929
"Enables all logging possible, please use this setting when submitting logs for bug reports!",
930-
"Enables more logging than normal.",
931-
"The default logging level.",
932-
"Only log warnings and errors.",
930+
"Enables more detailed logging of the extension",
931+
"Logs high-level information about what the extension is doing.",
932+
"Only log warnings and errors. This is the default setting",
933933
"Only log errors.",
934934
"Disable all logging possible. No log files will be written!"
935935
],
936-
"markdownDescription": "Sets the log verbosity for both the extension and its LSP server, PowerShell Editor Services. **Please set to `Diagnostic` when recording logs for a bug report!**"
936+
"markdownDescription": "Sets the log verbosity for both the extension and its LSP server, PowerShell Editor Services. **Please set to `Trace` when recording logs for a bug report!**"
937937
},
938938
"powershell.developer.editorServicesWaitForDebugger": {
939939
"type": "boolean",
@@ -953,6 +953,21 @@
953953
"default": [],
954954
"markdownDescription": "An array of strings that enable experimental features in the PowerShell extension. **No flags are currently available!**"
955955
},
956+
"powershell.developer.traceDap": {
957+
"type": "boolean",
958+
"default": false,
959+
"markdownDescription": "Traces the DAP communication between VS Code and the PowerShell Editor Services [DAP Server](https://microsoft.github.io/debug-adapter-protocol/). The output will be logged and also visible in the Output pane, where the verbosity is configurable. **For extension developers and issue troubleshooting only!**"
960+
},
961+
"powershell.trace.server": {
962+
"type": "string",
963+
"enum": [
964+
"off",
965+
"messages",
966+
"verbose"
967+
],
968+
"default": "off",
969+
"markdownDescription": "Traces the communication between VS Code and the PowerShell Editor Services [LSP Server](https://microsoft.github.io/language-server-protocol/). The output will be logged and also visible in the Output pane, where the verbosity is configurable. **For extension developers and issue troubleshooting only!**"
970+
},
956971
"powershell.developer.waitForSessionFileTimeoutSeconds": {
957972
"type": "number",
958973
"default": 240,
@@ -1002,21 +1017,6 @@
10021017
"type": "boolean",
10031018
"default": false,
10041019
"markdownDescription": "Show buttons in the editor's title bar for moving the terminals pane (with the PowerShell Extension Terminal) around."
1005-
},
1006-
"powershell.trace.server": {
1007-
"type": "string",
1008-
"enum": [
1009-
"off",
1010-
"messages",
1011-
"verbose"
1012-
],
1013-
"default": "off",
1014-
"markdownDescription": "Traces the communication between VS Code and the PowerShell Editor Services [LSP Server](https://microsoft.github.io/language-server-protocol/). **only for extension developers and issue troubleshooting!**"
1015-
},
1016-
"powershell.trace.dap": {
1017-
"type": "boolean",
1018-
"default": false,
1019-
"markdownDescription": "Traces the communication between VS Code and the PowerShell Editor Services [DAP Server](https://microsoft.github.io/debug-adapter-protocol/). **This setting is only meant for extension developers and issue troubleshooting!**"
10201020
}
10211021
}
10221022
},

‎src/extension.ts‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { ShowHelpFeature } from "./features/ShowHelp";
2222
import { SpecifyScriptArgsFeature } from "./features/DebugSession";
2323
import { Logger } from "./logging";
2424
import { SessionManager } from "./session";
25-
import { LogLevel, getSettings } from "./settings";
25+
import { getSettings } from "./settings";
2626
import { PowerShellLanguageId } from "./utils";
2727
import { LanguageClientConsumer } from "./languageClientConsumer";
2828

@@ -43,14 +43,12 @@ const documentSelector: DocumentSelector = [
4343
];
4444

4545
export async function activate(context: vscode.ExtensionContext): Promise<IPowerShellExtensionClient> {
46-
const logLevel = vscode.workspace.getConfiguration(`${PowerShellLanguageId}.developer`)
47-
.get<string>("editorServicesLogLevel", LogLevel.Normal);
48-
logger = new Logger(logLevel, context.globalStorageUri);
46+
logger = new Logger();
4947

5048
telemetryReporter = new TelemetryReporter(TELEMETRY_KEY);
5149

5250
const settings = getSettings();
53-
logger.writeVerbose(`Loaded settings:\n${JSON.stringify(settings, undefined, 2)}`);
51+
logger.writeDebug(`Loaded settings:\n${JSON.stringify(settings, undefined, 2)}`);
5452

5553
languageConfigurationDisposable = vscode.languages.setLanguageConfiguration(
5654
PowerShellLanguageId,
@@ -141,6 +139,19 @@ export async function activate(context: vscode.ExtensionContext): Promise<IPower
141139
new PesterTestsFeature(sessionManager, logger),
142140
new CodeActionsFeature(logger),
143141
new SpecifyScriptArgsFeature(context),
142+
143+
vscode.commands.registerCommand(
144+
"PowerShell.OpenLogFolder",
145+
async () => {await vscode.commands.executeCommand(
146+
"vscode.openFolder",
147+
context.logUri,
148+
{ forceNewWindow: true }
149+
);}
150+
),
151+
vscode.commands.registerCommand(
152+
"PowerShell.ShowLogs",
153+
() => {logger.showLogPanel();}
154+
)
144155
];
145156

146157
const externalApi = new ExternalApiFeature(context, sessionManager, logger);
@@ -169,6 +180,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<IPower
169180
getPowerShellVersionDetails: uuid => externalApi.getPowerShellVersionDetails(uuid),
170181
waitUntilStarted: uuid => externalApi.waitUntilStarted(uuid),
171182
getStorageUri: () => externalApi.getStorageUri(),
183+
getLogUri: () => externalApi.getLogUri(),
172184
};
173185
}
174186

‎src/features/DebugSession.ts‎

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,8 @@ export class DebugSessionFeature extends LanguageClientConsumer
335335
// Create or show the debug terminal (either temporary or session).
336336
this.sessionManager.showDebugTerminal(true);
337337

338-
this.logger.writeVerbose(`Connecting to pipe: ${sessionDetails.debugServicePipeName}`);
339-
this.logger.writeVerbose(`Debug configuration: ${JSON.stringify(session.configuration, undefined, 2)}`);
338+
this.logger.writeDebug(`Connecting to pipe: ${sessionDetails.debugServicePipeName}`);
339+
this.logger.writeDebug(`Debug configuration: ${JSON.stringify(session.configuration, undefined, 2)}`);
340340

341341
return new DebugAdapterNamedPipeServer(sessionDetails.debugServicePipeName);
342342
}
@@ -424,7 +424,7 @@ export class DebugSessionFeature extends LanguageClientConsumer
424424
// The dispose shorthand demonry for making an event one-time courtesy of: https://github.com/OmniSharp/omnisharp-vscode/blob/b8b07bb12557b4400198895f82a94895cb90c461/test/integrationTests/launchConfiguration.integration.test.ts#L41-L45
425425
startDebugEvent.dispose();
426426

427-
this.logger.writeVerbose(`Debugger session detected: ${dotnetAttachSession.name} (${dotnetAttachSession.id})`);
427+
this.logger.writeDebug(`Debugger session detected: ${dotnetAttachSession.name} (${dotnetAttachSession.id})`);
428428

429429
tempConsoleDotnetAttachSession = dotnetAttachSession;
430430

@@ -434,7 +434,7 @@ export class DebugSessionFeature extends LanguageClientConsumer
434434
// Makes the event one-time
435435
stopDebugEvent.dispose();
436436

437-
this.logger.writeVerbose(`Debugger session terminated: ${tempConsoleSession.name} (${tempConsoleSession.id})`);
437+
this.logger.writeDebug(`Debugger session terminated: ${tempConsoleSession.name} (${tempConsoleSession.id})`);
438438

439439
// HACK: As of 2023-08-17, there is no vscode debug API to request the C# debugger to detach, so we send it a custom DAP request instead.
440440
const disconnectRequest: DebugProtocol.DisconnectRequest = {
@@ -462,8 +462,8 @@ export class DebugSessionFeature extends LanguageClientConsumer
462462
// Start a child debug session to attach the dotnet debugger
463463
// TODO: Accommodate multi-folder workspaces if the C# code is in a different workspace folder
464464
await debug.startDebugging(undefined, dotnetAttachConfig, session);
465-
this.logger.writeVerbose(`Dotnet attach debug configuration: ${JSON.stringify(dotnetAttachConfig, undefined, 2)}`);
466-
this.logger.writeVerbose(`Attached dotnet debugger to process: ${pid}`);
465+
this.logger.writeDebug(`Dotnet attach debug configuration: ${JSON.stringify(dotnetAttachConfig, undefined, 2)}`);
466+
this.logger.writeDebug(`Attached dotnet debugger to process: ${pid}`);
467467
}
468468

469469
return this.tempSessionDetails;
@@ -606,36 +606,27 @@ export class DebugSessionFeature extends LanguageClientConsumer
606606

607607
class PowerShellDebugAdapterTrackerFactory implements DebugAdapterTrackerFactory, Disposable {
608608
disposables: Disposable[] = [];
609-
dapLogEnabled: boolean = workspace.getConfiguration("powershell").get<boolean>("trace.dap") ?? false;
610-
constructor(private adapterName = "PowerShell") {
611-
this.disposables.push(workspace.onDidChangeConfiguration(change => {
612-
if (
613-
change.affectsConfiguration("powershell.trace.dap")
614-
) {
615-
this.dapLogEnabled = workspace.getConfiguration("powershell").get<boolean>("trace.dap") ?? false;
616-
if (this.dapLogEnabled) {
617-
// Trigger the output pane to appear. This gives the user time to position it before starting a debug.
618-
this.log?.show(true);
619-
}
620-
}
621-
}));
622-
}
609+
constructor(private adapterName = "PowerShell") {}
623610

624-
/* We want to use a shared output log for separate debug sessions as usually only one is running at a time and we
625-
* dont need an output window for every debug session. We also want to leave it active so user can copy and paste
626-
* even on run end. When user changes the setting and disables it getter will return undefined, which will result
611+
612+
_log: LogOutputChannel | undefined;
613+
/** Lazily creates a {@link LogOutputChannel} for debug tracing, and presents it only when DAP logging is enabled.
614+
*
615+
* We want to use a shared output log for separate debug sessions as usually only one is running at a time and we
616+
* dont need an output window for every debug session. We also want to leave it active so user can copy and paste
617+
* even on run end. When user changes the setting and disables it getter will return undefined, which will result
627618
* in a noop for the logging activities, effectively pausing logging but not disposing the output channel. If the
628619
* user re-enables, then logging resumes.
629620
*/
630-
_log: LogOutputChannel | undefined;
631621
get log(): LogOutputChannel | undefined {
632-
if (this.dapLogEnabled && this._log === undefined) {
633-
this._log = window.createOutputChannel(`${this.adapterName} Trace - DAP`, { log: true });
622+
if (workspace.getConfiguration("powershell.developer").get<boolean>("traceDap") && this._log === undefined) {
623+
this._log = window.createOutputChannel(`${this.adapterName}: Trace DAP`, { log: true });
634624
this.disposables.push(this._log);
635625
}
636-
return this.dapLogEnabled ? this._log : undefined;
626+
return this._log;
637627
}
638628

629+
// This tracker effectively implements the logging for the debug adapter to a LogOutputChannel
639630
createDebugAdapterTracker(session: DebugSession): DebugAdapterTracker {
640631
const sessionInfo = `${this.adapterName} Debug Session: ${session.name} [${session.id}]`;
641632
return {

‎src/features/ExternalApi.ts‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface IPowerShellExtensionClient {
1919
getPowerShellVersionDetails(uuid: string): Promise<IExternalPowerShellDetails>;
2020
waitUntilStarted(uuid: string): Promise<void>;
2121
getStorageUri(): vscode.Uri;
22+
getLogUri(): vscode.Uri;
2223
}
2324

2425
/*
@@ -55,7 +56,7 @@ export class ExternalApiFeature implements IPowerShellExtensionClient {
5556
string session uuid
5657
*/
5758
public registerExternalExtension(id: string, apiVersion = "v1"): string {
58-
this.logger.writeVerbose(`Registering extension '${id}' for use with API version '${apiVersion}'.`);
59+
this.logger.writeDebug(`Registering extension '${id}' for use with API version '${apiVersion}'.`);
5960

6061
// eslint-disable-next-line @typescript-eslint/no-unused-vars
6162
for (const [_name, externalExtension] of ExternalApiFeature.registeredExternalExtension) {
@@ -96,7 +97,7 @@ export class ExternalApiFeature implements IPowerShellExtensionClient {
9697
true if it worked, otherwise throws an error.
9798
*/
9899
public unregisterExternalExtension(uuid = ""): boolean {
99-
this.logger.writeVerbose(`Unregistering extension with session UUID: ${uuid}`);
100+
this.logger.writeDebug(`Unregistering extension with session UUID: ${uuid}`);
100101
if (!ExternalApiFeature.registeredExternalExtension.delete(uuid)) {
101102
throw new Error(`No extension registered with session UUID: ${uuid}`);
102103
}
@@ -133,7 +134,7 @@ export class ExternalApiFeature implements IPowerShellExtensionClient {
133134
*/
134135
public async getPowerShellVersionDetails(uuid = ""): Promise<IExternalPowerShellDetails> {
135136
const extension = this.getRegisteredExtension(uuid);
136-
this.logger.writeVerbose(`Extension '${extension.id}' called 'getPowerShellVersionDetails'.`);
137+
this.logger.writeDebug(`Extension '${extension.id}' called 'getPowerShellVersionDetails'.`);
137138

138139
await this.sessionManager.waitUntilStarted();
139140
const versionDetails = this.sessionManager.getPowerShellVersionDetails();
@@ -161,7 +162,7 @@ export class ExternalApiFeature implements IPowerShellExtensionClient {
161162
*/
162163
public async waitUntilStarted(uuid = ""): Promise<void> {
163164
const extension = this.getRegisteredExtension(uuid);
164-
this.logger.writeVerbose(`Extension '${extension.id}' called 'waitUntilStarted'.`);
165+
this.logger.writeDebug(`Extension '${extension.id}' called 'waitUntilStarted'.`);
165166
await this.sessionManager.waitUntilStarted();
166167
}
167168

@@ -171,6 +172,10 @@ export class ExternalApiFeature implements IPowerShellExtensionClient {
171172
return this.extensionContext.globalStorageUri.with({ scheme: "file"});
172173
}
173174

175+
public getLogUri(): vscode.Uri {
176+
return this.extensionContext.logUri.with({ scheme: "file"});
177+
}
178+
174179
public dispose(): void {
175180
// Nothing to dispose.
176181
}

‎src/features/UpdatePowerShell.ts‎

Lines changed: 12 additions & 12 deletions

0 commit comments

Comments
 (0)