Skip to content

Commit

Permalink
feat: add "Show Logs" command to help with network debugging (#166)
Browse files Browse the repository at this point in the history
  • Loading branch information
kylecarbs authored Nov 14, 2023
1 parent 1aee70c commit 4a7350a
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 5 deletions.
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "coder-remote",
"publisher": "coder",
"displayName": "Coder Remote",
"displayName": "Coder",
"description": "Open any workspace with a single click.",
"repository": "https://github.com/coder/vscode-coder",
"version": "0.1.26",
Expand Down Expand Up @@ -168,6 +168,12 @@
"title": "Coder: Refresh Workspace",
"icon": "$(refresh)",
"when": "coder.authenticated"
},
{
"command": "coder.viewLogs",
"title": "Coder: View Logs",
"icon": "$(list-unordered)",
"when": "coder.authenticated"
}
],
"menus": {
Expand Down
11 changes: 11 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,17 @@ export class Commands {
}
}

// viewLogs opens the workspace logs.
public async viewLogs(): Promise<void> {
if (!this.storage.workspaceLogPath) {
vscode.window.showInformationMessage("No logs available.", this.storage.workspaceLogPath || "<unset>")
return
}
const uri = vscode.Uri.file(this.storage.workspaceLogPath)
const doc = await vscode.workspace.openTextDocument(uri)
await vscode.window.showTextDocument(doc)
}

public async logout(): Promise<void> {
await this.storage.setURL(undefined)
await this.storage.setSessionToken(undefined)
Expand Down
1 change: 1 addition & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
myWorkspacesProvider.fetchAndRefresh()
allWorkspacesProvider.fetchAndRefresh()
})
vscode.commands.registerCommand("coder.viewLogs", commands.viewLogs.bind(commands))

// Since the "onResolveRemoteAuthority:ssh-remote" activation event exists
// in package.json we're able to perform actions before the authority is
Expand Down
17 changes: 13 additions & 4 deletions src/remote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ export class Remote {
await this.closeRemote()
return
}
// CLI versions before 2.3.3 don't support the --log-dir flag!
// If this check didn't exist, VS Code connections would fail on
// older versions because of an unknown CLI argument.
const hasCoderLogs = (parsedVersion?.compare("2.3.3") || 0) >= 0 || parsedVersion?.prerelease[0] === "devel"

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

this.findSSHProcessID().then((pid) => {
if (!pid) {
// TODO: Show an error here!
return
}
disposables.push(this.showNetworkUpdates(pid))
this.storage.workspaceLogPath = path.join(this.storage.getLogPath(), `${pid}.log`)
})

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

// updateSSHConfig updates the SSH configuration with a wildcard that handles
// all Coder entries.
private async updateSSHConfig(hostName: string) {
private async updateSSHConfig(hostName: string, hasCoderLogs = false) {
let deploymentSSHConfig = defaultSSHConfigResponse
try {
const deploymentConfig = await getDeploymentSSHConfig()
Expand Down Expand Up @@ -542,12 +547,16 @@ export class Remote {
if (typeof headerCommand === "string" && headerCommand.trim().length > 0) {
headerArg = ` --header-command ${escape(headerCommand)}`
}

let logArg = ""
if (hasCoderLogs) {
await fs.mkdir(this.storage.getLogPath(), { recursive: true })
logArg = ` --log-dir ${escape(this.storage.getLogPath())}`
}
const sshValues: SSHValues = {
Host: `${Remote.Prefix}*`,
ProxyCommand: `${escape(binaryPath)}${headerArg} vscodessh --network-info-dir ${escape(
this.storage.getNetworkInfoPath(),
)} --session-token-file ${escape(this.storage.getSessionTokenPath())} --url-file ${escape(
)}${logArg} --session-token-file ${escape(this.storage.getSessionTokenPath())} --url-file ${escape(
this.storage.getURLPath(),
)} %h`,
ConnectTimeout: "0",
Expand Down
7 changes: 7 additions & 0 deletions src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getHeaderCommand, getHeaders } from "./headers"

export class Storage {
public workspace?: Workspace
public workspaceLogPath?: string

constructor(
private readonly output: vscode.OutputChannel,
Expand Down Expand Up @@ -279,6 +280,12 @@ export class Storage {
return path.join(this.globalStorageUri.fsPath, "net")
}

// getLogPath returns the path where log data from the Coder
// agent is stored.
public getLogPath(): string {
return path.join(this.globalStorageUri.fsPath, "log")
}

public getUserSettingsPath(): string {
return path.join(this.globalStorageUri.fsPath, "..", "..", "..", "User", "settings.json")
}
Expand Down

0 comments on commit 4a7350a

Please sign in to comment.