Skip to content

Commit 4a7350a

Browse files
authored
feat: add "Show Logs" command to help with network debugging (#166)
1 parent 1aee70c commit 4a7350a

File tree

5 files changed

+39
-5
lines changed

5 files changed

+39
-5
lines changed

package.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "coder-remote",
33
"publisher": "coder",
4-
"displayName": "Coder Remote",
4+
"displayName": "Coder",
55
"description": "Open any workspace with a single click.",
66
"repository": "https://github.com/coder/vscode-coder",
77
"version": "0.1.26",
@@ -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

+11
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

+1
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

+13-4
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ 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.
82+
const hasCoderLogs = (parsedVersion?.compare("2.3.3") || 0) >= 0 || parsedVersion?.prerelease[0] === "devel"
7983

8084
// Find the workspace from the URI scheme provided!
8185
try {
@@ -426,14 +430,15 @@ export class Remote {
426430
//
427431
// If we didn't write to the SSH config file, connecting would fail with
428432
// "Host not found".
429-
await this.updateSSHConfig(authorityParts[1])
433+
await this.updateSSHConfig(authorityParts[1], hasCoderLogs)
430434

431435
this.findSSHProcessID().then((pid) => {
432436
if (!pid) {
433437
// TODO: Show an error here!
434438
return
435439
}
436440
disposables.push(this.showNetworkUpdates(pid))
441+
this.storage.workspaceLogPath = path.join(this.storage.getLogPath(), `${pid}.log`)
437442
})
438443

439444
// Register the label formatter again because SSH overrides it!
@@ -456,7 +461,7 @@ export class Remote {
456461

457462
// updateSSHConfig updates the SSH configuration with a wildcard that handles
458463
// all Coder entries.
459-
private async updateSSHConfig(hostName: string) {
464+
private async updateSSHConfig(hostName: string, hasCoderLogs = false) {
460465
let deploymentSSHConfig = defaultSSHConfigResponse
461466
try {
462467
const deploymentConfig = await getDeploymentSSHConfig()
@@ -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

+7
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)