Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 400fd75

Browse files
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

File tree

12 files changed

+422
-245
lines changed

12 files changed

+422
-245
lines changed

‎docs/troubleshooting.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,11 @@ Logs provide context for what was happening when the issue occurred. **You shoul
253253
your logs for any sensitive information you would not like to share online!**
254254

255255
* Before sending through logs, try and reproduce the issue with **log level set to
256-
Diagnostic**. You can set this in the [VS Code Settings][]
256+
Trace**. You can set this in the [VS Code Settings][]
257257
(<kbd>Ctrl</kbd>+<kbd>,</kbd>) with:
258258

259259
```json
260-
"powershell.developer.editorServicesLogLevel": "Diagnostic"
260+
"powershell.developer.editorServicesLogLevel": "Trace"
261261
```
262262

263263
* After you have captured the issue with the log level turned up, you may want to return

‎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
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,20 @@ export class UpdatePowerShell {
5151
private shouldCheckForUpdate(): boolean {
5252
// Respect user setting.
5353
if (!this.sessionSettings.promptToUpdatePowerShell) {
54-
this.logger.writeVerbose("Setting 'promptToUpdatePowerShell' was false.");
54+
this.logger.writeDebug("Setting 'promptToUpdatePowerShell' was false.");
5555
return false;
5656
}
5757

5858
// Respect environment configuration.
5959
if (process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "off") {
60-
this.logger.writeVerbose("Environment variable 'POWERSHELL_UPDATECHECK' was 'Off'.");
60+
this.logger.writeDebug("Environment variable 'POWERSHELL_UPDATECHECK' was 'Off'.");
6161
return false;
6262
}
6363

6464
// Skip prompting when using Windows PowerShell for now.
6565
if (this.localVersion.compare("6.0.0") === -1) {
6666
// TODO: Maybe we should announce PowerShell Core?
67-
this.logger.writeVerbose("Not prompting to update Windows PowerShell.");
67+
this.logger.writeDebug("Not prompting to update Windows PowerShell.");
6868
return false;
6969
}
7070

@@ -78,13 +78,13 @@ export class UpdatePowerShell {
7878

7979
// Skip if PowerShell is self-built, that is, this contains a commit hash.
8080
if (commit.length >= 40) {
81-
this.logger.writeVerbose("Not prompting to update development build.");
81+
this.logger.writeDebug("Not prompting to update development build.");
8282
return false;
8383
}
8484

8585
// Skip if preview is a daily build.
8686
if (daily.toLowerCase().startsWith("daily")) {
87-
this.logger.writeVerbose("Not prompting to update daily build.");
87+
this.logger.writeDebug("Not prompting to update daily build.");
8888
return false;
8989
}
9090
}
@@ -106,7 +106,7 @@ export class UpdatePowerShell {
106106
// "ReleaseTag": "v7.2.7"
107107
// }
108108
const data = await response.json();
109-
this.logger.writeVerbose(`Received from '${url}':\n${JSON.stringify(data, undefined, 2)}`);
109+
this.logger.writeDebug(`Received from '${url}':\n${JSON.stringify(data, undefined, 2)}`);
110110
return data.ReleaseTag;
111111
}
112112

@@ -115,26 +115,26 @@ export class UpdatePowerShell {
115115
return undefined;
116116
}
117117

118-
this.logger.writeVerbose("Checking for PowerShell update...");
118+
this.logger.writeDebug("Checking for PowerShell update...");
119119
const tags: string[] = [];
120120
if (process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "lts") {
121121
// Only check for update to LTS.
122-
this.logger.writeVerbose("Checking for LTS update...");
122+
this.logger.writeDebug("Checking for LTS update...");
123123
const tag = await this.getRemoteVersion(UpdatePowerShell.LTSBuildInfoURL);
124124
if (tag != undefined) {
125125
tags.push(tag);
126126
}
127127
} else {
128128
// Check for update to stable.
129-
this.logger.writeVerbose("Checking for stable update...");
129+
this.logger.writeDebug("Checking for stable update...");
130130
const tag = await this.getRemoteVersion(UpdatePowerShell.StableBuildInfoURL);
131131
if (tag != undefined) {
132132
tags.push(tag);
133133
}
134134

135135
// Also check for a preview update.
136136
if (this.localVersion.prerelease.length > 0) {
137-
this.logger.writeVerbose("Checking for preview update...");
137+
this.logger.writeDebug("Checking for preview update...");
138138
const tag = await this.getRemoteVersion(UpdatePowerShell.PreviewBuildInfoURL);
139139
if (tag != undefined) {
140140
tags.push(tag);
@@ -181,11 +181,11 @@ export class UpdatePowerShell {
181181

182182
// If the user cancels the notification.
183183
if (!result) {
184-
this.logger.writeVerbose("User canceled PowerShell update prompt.");
184+
this.logger.writeDebug("User canceled PowerShell update prompt.");
185185
return;
186186
}
187187

188-
this.logger.writeVerbose(`User said '${UpdatePowerShell.promptOptions[result.id].title}'.`);
188+
this.logger.writeDebug(`User said '${UpdatePowerShell.promptOptions[result.id].title}'.`);
189189

190190
switch (result.id) {
191191
// Yes

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /