Skip to content

Commit 5ad161b

Browse files
committed
feat: add "Show Logs" command to help with network debugging
1 parent ba1717a commit 5ad161b

File tree

5 files changed

+53
-19
lines changed

5 files changed

+53
-19
lines changed

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@
168168
"title": "Coder: Refresh Workspace",
169169
"icon": "$(refresh)",
170170
"when": "coder.authenticated"
171+
},
172+
{
173+
"command": "coder.viewLogs",
174+
"title": "Coder: View Logs",
175+
"icon": "$(list-unordered)",
176+
"when": "coder.authenticated"
171177
}
172178
],
173179
"menus": {

src/commands.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,17 @@ export class Commands {
115115
}
116116
}
117117

118+
// viewLogs opens the workspace logs.
119+
public async viewLogs(): Promise<void> {
120+
if (!this.storage.workspaceLogPath) {
121+
vscode.window.showInformationMessage("No logs available.", this.storage.workspaceLogPath || "<unset>")
122+
return
123+
}
124+
const uri = vscode.Uri.file(this.storage.workspaceLogPath)
125+
const doc = await vscode.workspace.openTextDocument(uri)
126+
await vscode.window.showTextDocument(doc)
127+
}
128+
118129
public async logout(): Promise<void> {
119130
await this.storage.setURL(undefined)
120131
await this.storage.setSessionToken(undefined)

src/extension.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
157157
myWorkspacesProvider.fetchAndRefresh()
158158
allWorkspacesProvider.fetchAndRefresh()
159159
})
160+
vscode.commands.registerCommand("coder.viewLogs", commands.viewLogs.bind(commands))
160161

161162
// Since the "onResolveRemoteAuthority:ssh-remote" activation event exists
162163
// in package.json we're able to perform actions before the authority is

src/remote.ts

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,11 @@ export class Remote {
7676
await this.closeRemote()
7777
return
7878
}
79+
// CLI versions before 2.3.3 don't support the --log-dir flag!
80+
// If this check didn't exist, VS Code connections would fail on
81+
// older versions because of an unknown CLI argument.
7982
const hasCoderLogs = (parsedVersion?.compare("2.3.3") || 0) >= 0 || parsedVersion?.prerelease[0] === "devel"
8083

81-
console.log("hasCoderLogs", hasCoderLogs)
82-
8384
// Find the workspace from the URI scheme provided!
8485
try {
8586
this.storage.workspace = await getWorkspaceByOwnerAndName(parts[0], parts[1])
@@ -429,14 +430,15 @@ export class Remote {
429430
//
430431
// If we didn't write to the SSH config file, connecting would fail with
431432
// "Host not found".
432-
await this.updateSSHConfig(authorityParts[1])
433+
await this.updateSSHConfig(authorityParts[1], hasCoderLogs)
433434

434435
this.findSSHProcessID().then((pid) => {
435436
if (!pid) {
436437
// TODO: Show an error here!
437438
return
438439
}
439440
disposables.push(this.showNetworkUpdates(pid))
441+
this.storage.workspaceLogPath = path.join(this.storage.getLogPath(), `${pid}.log`)
440442
})
441443

442444
// Register the label formatter again because SSH overrides it!
@@ -459,7 +461,7 @@ export class Remote {
459461

460462
// updateSSHConfig updates the SSH configuration with a wildcard that handles
461463
// all Coder entries.
462-
private async updateSSHConfig(hostName: string) {
464+
private async updateSSHConfig(hostName: string, hasCoderLogs = false) {
463465
let deploymentSSHConfig = defaultSSHConfigResponse
464466
try {
465467
const deploymentConfig = await getDeploymentSSHConfig()
@@ -487,21 +489,24 @@ export class Remote {
487489
// Now override with the user's config.
488490
const userConfigSSH = vscode.workspace.getConfiguration("coder").get<string[]>("sshConfig") || []
489491
// Parse the user's config into a Record<string, string>.
490-
const userConfig = userConfigSSH.reduce((acc, line) => {
491-
let i = line.indexOf("=")
492-
if (i === -1) {
493-
i = line.indexOf(" ")
492+
const userConfig = userConfigSSH.reduce(
493+
(acc, line) => {
494+
let i = line.indexOf("=")
494495
if (i === -1) {
495-
// This line is malformed. The setting is incorrect, and does not match
496-
// the pattern regex in the settings schema.
497-
return acc
496+
i = line.indexOf(" ")
497+
if (i === -1) {
498+
// This line is malformed. The setting is incorrect, and does not match
499+
// the pattern regex in the settings schema.
500+
return acc
501+
}
498502
}
499-
}
500-
const key = line.slice(0, i)
501-
const value = line.slice(i + 1)
502-
acc[key] = value
503-
return acc
504-
}, {} as Record<string, string>)
503+
const key = line.slice(0, i)
504+
const value = line.slice(i + 1)
505+
acc[key] = value
506+
return acc
507+
},
508+
{} as Record<string, string>,
509+
)
505510
const sshConfigOverrides = mergeSSHConfigValues(deploymentSSHConfig, userConfig)
506511

507512
let sshConfigFile = vscode.workspace.getConfiguration().get<string>("remote.SSH.configFile")
@@ -542,12 +547,16 @@ export class Remote {
542547
if (typeof headerCommand === "string" && headerCommand.trim().length > 0) {
543548
headerArg = ` --header-command ${escape(headerCommand)}`
544549
}
545-
550+
let logArg = ""
551+
if (hasCoderLogs) {
552+
await fs.mkdir(this.storage.getLogPath(), { recursive: true })
553+
logArg = ` --log-dir ${escape(this.storage.getLogPath())}`
554+
}
546555
const sshValues: SSHValues = {
547556
Host: `${Remote.Prefix}*`,
548557
ProxyCommand: `${escape(binaryPath)}${headerArg} vscodessh --network-info-dir ${escape(
549558
this.storage.getNetworkInfoPath(),
550-
)} --session-token-file ${escape(this.storage.getSessionTokenPath())} --url-file ${escape(
559+
)}${logArg} --session-token-file ${escape(this.storage.getSessionTokenPath())} --url-file ${escape(
551560
this.storage.getURLPath(),
552561
)} %h`,
553562
ConnectTimeout: "0",

src/storage.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { getHeaderCommand, getHeaders } from "./headers"
1515

1616
export class Storage {
1717
public workspace?: Workspace
18+
public workspaceLogPath?: string
1819

1920
constructor(
2021
private readonly output: vscode.OutputChannel,
@@ -279,6 +280,12 @@ export class Storage {
279280
return path.join(this.globalStorageUri.fsPath, "net")
280281
}
281282

283+
// getLogPath returns the path where log data from the Coder
284+
// agent is stored.
285+
public getLogPath(): string {
286+
return path.join(this.globalStorageUri.fsPath, "log")
287+
}
288+
282289
public getUserSettingsPath(): string {
283290
return path.join(this.globalStorageUri.fsPath, "..", "..", "..", "User", "settings.json")
284291
}

0 commit comments

Comments
 (0)