Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Collect all logs command to gitpod-desktop #344

Merged
merged 1 commit into from
Apr 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions extensions/gitpod-remote/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ export async function activate(context: vscode.ExtensionContext) {
if (!gitpodContext) {
return;
}

if (vscode.extensions.getExtension('gitpod.gitpod')) {
try {
await util.promisify(cp.exec)('code --uninstall-extension gitpod.gitpod');
vscode.commands.executeCommand('workbench.action.reloadWindow');
} catch (e) {
gitpodContext.output.appendLine('failed to uninstall gitpod.gitpod: ' + e);
gitpodContext.logger.error('failed to uninstall gitpod.gitpod:', e);
}
return;
}
Expand All @@ -43,6 +44,11 @@ export async function activate(context: vscode.ExtensionContext) {
// and gitpod.gitpod to disable auto tunneling from the current local machine.
vscode.commands.executeCommand('gitpod.api.autoTunnel', gitpodContext.info.getGitpodHost(), gitpodContext.info.getInstanceId(), false);

// For collecting logs, will be called by gitpod-desktop extension;
context.subscriptions.push(vscode.commands.registerCommand('__gitpod.getGitpodRemoteLogsUri', () => {
return context.logUri;
}));

// TODO
// - auth?
// - .gitpod.yml validations
Expand Down Expand Up @@ -87,7 +93,7 @@ export function openWorkspaceLocation(context: GitpodExtensionContext): boolean
}

export async function installInitialExtensions(context: GitpodExtensionContext): Promise<void> {
context.output.appendLine('installing initial extensions...');
context.logger.info('installing initial extensions...');
const extensions: (vscode.Uri | string)[] = [];
try {
const workspaceContextUri = vscode.Uri.parse(context.info.getWorkspaceContextUrl());
Expand Down Expand Up @@ -125,10 +131,10 @@ export async function installInitialExtensions(context: GitpodExtensionContext):
}
}
} catch (e) {
context.output.appendLine('failed to detect workspace context dependent extensions:' + e);
context.logger.error('failed to detect workspace context dependent extensions:', e);
console.error('failed to detect workspace context dependent extensions:', e);
}
context.output.appendLine('initial extensions: ' + extensions);
context.logger.info('initial extensions:', extensions);
if (extensions.length) {
let cause;
try {
Expand All @@ -138,11 +144,11 @@ export async function installInitialExtensions(context: GitpodExtensionContext):
cause = e;
}
if (cause) {
context.output.appendLine('failed to install initial extensions: ' + cause);
context.logger.error('failed to install initial extensions:', cause);
console.error('failed to install initial extensions: ', cause);
}
}
context.output.appendLine('initial extensions installed');
context.logger.info('initial extensions installed');
}

export function registerHearbeat(context: GitpodExtensionContext): void {
Expand All @@ -152,11 +158,13 @@ export function registerHearbeat(context: GitpodExtensionContext): void {
};
const sendHeartBeat = async (wasClosed?: true) => {
const suffix = wasClosed ? 'was closed heartbeat' : 'heartbeat';
if (wasClosed) {
context.logger.trace('sending ' + suffix);
}
try {
context.output.appendLine('sending ' + suffix);
await context.gitpod.server.sendHeartBeat({ instanceId: context.info.getInstanceId(), wasClosed });
} catch (err) {
context.output.appendLine(`failed to send ${suffix}: ` + err);
context.logger.error(`failed to send ${suffix}:`, err);
console.error(`failed to send ${suffix}`, err);
}
};
Expand Down
67 changes: 67 additions & 0 deletions extensions/gitpod-shared/src/common/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Gitpod. All rights reserved.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';

type LogLevel = 'Trace' | 'Info' | 'Error' | 'Warn' | 'Log';

export default class Log {
private output: vscode.OutputChannel;

constructor(name: string) {
this.output = vscode.window.createOutputChannel(name);
}

private data2String(data: any): string {
if (data instanceof Error) {
return data.stack || data.message;
}
if (data.success === false && data.message) {
return data.message;
}
return data.toString();
}

public trace(message: string, data?: any): void {
this.logLevel('Trace', message, data);
}

public info(message: string, data?: any): void {
this.logLevel('Info', message, data);
}

public error(message: string, data?: any): void {
this.logLevel('Error', message, data);
}

public warn(message: string, data?: any): void {
this.logLevel('Warn', message, data);
}

public log(message: string, data?: any): void {
this.logLevel('Log', message, data);
}

public logLevel(level: LogLevel, message: string, data?: any): void {
this.output.appendLine(`[${level} - ${this.now()}] ${message}`);
if (data) {
this.output.appendLine(this.data2String(data));
}
}

private now(): string {
const now = new Date();
return padLeft(now.getUTCHours() + '', 2, '0')
+ ':' + padLeft(now.getMinutes() + '', 2, '0')
+ ':' + padLeft(now.getUTCSeconds() + '', 2, '0') + '.' + now.getMilliseconds();
}

public show() {
this.output.show();
}
}

function padLeft(s: string, n: number, pad = ' ') {
return pad.repeat(Math.max(0, n - s.length)) + s;
}
23 changes: 16 additions & 7 deletions extensions/gitpod-shared/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,15 @@ export async function setupGitpodContext(context: vscode.ExtensionContext): Prom
}

const gitpodContext = await createGitpodExtensionContext(context);
vscode.commands.executeCommand('setContext', 'gitpod.inWorkspace', !!gitpodContext);
if (!gitpodContext) {
vscode.commands.executeCommand('setContext', 'gitpod.inWorkspace', false);
return undefined;
}
vscode.commands.executeCommand('setContext', 'gitpod.inWorkspace', true);

logContextInfo(gitpodContext);

vscode.commands.executeCommand('setContext', 'gitpod.ideAlias', gitpodContext.info.getIdeAlias());
if (vscode.env.uiKind === vscode.UIKind.Web) {
vscode.commands.executeCommand('setContext', 'gitpod.UIKind', 'web');
} else if (vscode.env.uiKind === vscode.UIKind.Desktop) {
vscode.commands.executeCommand('setContext', 'gitpod.UIKind', 'desktop');
}
vscode.commands.executeCommand('setContext', 'gitpod.UIKind', vscode.env.uiKind === vscode.UIKind.Web ? 'web' : 'desktop');

registerUsageAnalytics(gitpodContext);
registerWorkspaceCommands(gitpodContext);
Expand All @@ -40,3 +37,15 @@ function registerUsageAnalytics(context: GitpodExtensionContext): void {
context.fireAnalyticsEvent({ eventName: 'vscode_session', properties: {} });
}

function logContextInfo(context: GitpodExtensionContext) {
context.logger.info(`VSCODE_MACHINE_ID: ${vscode.env.machineId}`);
context.logger.info(`VSCODE_SESSION_ID: ${vscode.env.sessionId}`);
context.logger.info(`VSCODE_VERSION: ${vscode.version}`);
context.logger.info(`VSCODE_APP_NAME: ${vscode.env.appName}`);
context.logger.info(`VSCODE_APP_HOST: ${vscode.env.appHost}`);
context.logger.info(`VSCODE_UI_KIND: ${vscode.env.uiKind === vscode.UIKind.Web ? 'web' : 'desktop'}`);

context.logger.info(`GITPOD_WORKSPACE_CONTEXT_URL: ${context.info.getWorkspaceContextUrl()}`);
context.logger.info(`GITPOD_INSTANCE_ID: ${context.info.getInstanceId()}`);
context.logger.info(`GITPOD_WORKSPACE_URL: ${context.info.getWorkspaceUrl()}`);
jeanp413 marked this conversation as resolved.
Show resolved Hide resolved
}
44 changes: 32 additions & 12 deletions extensions/gitpod-shared/src/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import WebSocket = require('ws');
import { BaseGitpodAnalyticsEventPropeties, GitpodAnalyticsEvent } from './analytics';
import * as uuid from 'uuid';
import { RemoteTrackMessage } from '@gitpod/gitpod-protocol/lib/analytics';
import Log from './common/logger';

export class SupervisorConnection {
readonly deadlines = {
Expand Down Expand Up @@ -94,7 +95,7 @@ export class GitpodExtensionContext implements vscode.ExtensionContext {
readonly user: Promise<User>,
readonly instanceListener: Promise<WorkspaceInstanceUpdateListener>,
readonly workspaceOwned: Promise<boolean>,
readonly output: vscode.OutputChannel,
readonly logger: Log,
readonly ipcHookCli: string | undefined
) {
this.workspaceContextUrl = vscode.Uri.parse(info.getWorkspaceContextUrl());
Expand Down Expand Up @@ -168,7 +169,7 @@ export class GitpodExtensionContext implements vscode.ExtensionContext {
await Promise.allSettled(this.pendingWillCloseSocket.map(f => f()));
webSocket.close();
} catch (e) {
this.output.appendLine('failed to dispose context: ' + e);
this.logger.error('failed to dispose context:', e);
console.error('failed to dispose context:', e);
}
})();
Expand All @@ -193,20 +194,20 @@ export class GitpodExtensionContext implements vscode.ExtensionContext {
}
};
if (this.devMode && vscode.env.uiKind === vscode.UIKind.Web) {
this.output.appendLine(`ANALYTICS: ${JSON.stringify(msg)} `);
this.logger.trace(`ANALYTICS: ${JSON.stringify(msg)} `);
return Promise.resolve();
}
try {
await this.gitpod.server.trackEvent(msg);
} catch (e) {
this.output.appendLine('failed to track event: ' + e);
this.logger.error('failed to track event:', e);
console.error('failed to track event:', e);
}
}
}

export async function createGitpodExtensionContext(context: vscode.ExtensionContext): Promise<GitpodExtensionContext | undefined> {
const output = vscode.window.createOutputChannel('Gitpod Workspace');
const logger = new Log('Gitpod Workspace');
const devMode = context.extensionMode === vscode.ExtensionMode.Development || !!process.env['VSCODE_DEV'];

const supervisor = new SupervisorConnection(context);
Expand All @@ -222,7 +223,7 @@ export async function createGitpodExtensionContext(context: vscode.ExtensionCont
contentAvailable = result.getAvailable();
} catch (e) {
if (e.code === grpc.status.UNAVAILABLE) {
output.appendLine('It does not look like we are running in a Gitpod workspace, supervisor is not available.');
logger.info('It does not look like we are running in a Gitpod workspace, supervisor is not available.');
return undefined;
}
console.error('cannot maintain connection to supervisor', e);
Expand Down Expand Up @@ -308,7 +309,7 @@ export async function createGitpodExtensionContext(context: vscode.ExtensionCont
return workspaceOwned;
})();

const ipcHookCli = installCLIProxy(context, output);
const ipcHookCli = installCLIProxy(context, logger);

const config = await import('./gitpod-plugin-model');
return new GitpodExtensionContext(
Expand All @@ -324,7 +325,7 @@ export async function createGitpodExtensionContext(context: vscode.ExtensionCont
pendingGetUser,
pendingInstanceListener,
pendingWorkspaceOwned,
output,
logger,
ipcHookCli
);
}
Expand Down Expand Up @@ -722,7 +723,7 @@ export function registerDefaultLayout(context: GitpodExtensionContext): void {
}
}

function installCLIProxy(context: vscode.ExtensionContext, output: vscode.OutputChannel): string | undefined {
function installCLIProxy(context: vscode.ExtensionContext, logger: Log): string | undefined {
const vscodeIpcHookCli = process.env['VSCODE_IPC_HOOK_CLI'];
if (!vscodeIpcHookCli) {
return undefined;
Expand Down Expand Up @@ -772,7 +773,7 @@ function installCLIProxy(context: vscode.ExtensionContext, output: vscode.Output
fs.promises.unlink(ipcHookCli)
));
}).catch(e => {
output.appendLine('failed to start cli proxy: ' + e);
logger.error('failed to start cli proxy: ' + e);
console.error('failed to start cli proxy:' + e);
});

Expand Down Expand Up @@ -815,6 +816,7 @@ export async function registerTasks(context: GitpodExtensionContext, createTermi
});
} catch (err) {
if (!('code' in err && err.code === grpc.status.CANCELLED)) {
context.logger.error('code server: listening task updates failed:', err);
console.error('code server: listening task updates failed:', err);
}
} finally {
Expand All @@ -824,6 +826,11 @@ export async function registerTasks(context: GitpodExtensionContext, createTermi
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
context.logger.trace('Task status:', [...tasks.values()].map(status => {
const stateMap = { [TaskState.OPENING]: 'CLOSED', [TaskState.RUNNING]: 'RUNNING', [TaskState.CLOSED]: 'CLOSED' };
return `\t${status.getTerminal()} => ${stateMap[status.getState()]}`;
}).join('\n'));

if (token.isCancellationRequested) {
return;
}
Expand All @@ -837,6 +844,7 @@ export async function registerTasks(context: GitpodExtensionContext, createTermi
taskTerminals.set(term.getAlias(), term);
}
} catch (e) {
context.logger.error('failed to list task terminals:', e);
console.error('failed to list task terminals:', e);
}

Expand Down Expand Up @@ -922,6 +930,7 @@ function createTaskPty(alias: string, context: GitpodExtensionContext, contextTo
} catch (e) {
notFound = 'code' in e && e.code === grpc.status.NOT_FOUND;
if (!token.isCancellationRequested && !notFound && !('code' in e && e.code === grpc.status.CANCELLED)) {
context.logger.error(`${alias} terminal: listening failed:`, e);
console.error(`${alias} terminal: listening failed:`, e);
}
} finally {
Expand All @@ -931,9 +940,16 @@ function createTaskPty(alias: string, context: GitpodExtensionContext, contextTo
return;
}
if (notFound) {
context.logger.trace(`${alias} terminal not found`);
onDidCloseEmitter.fire();
} else if (typeof exitCode === 'number') {
tokenSource.cancel();
return;
}
if (typeof exitCode === 'number') {
context.logger.trace(`${alias} terminal exited with ${exitCode}`);
onDidCloseEmitter.fire(exitCode);
tokenSource.cancel();
return;
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
Expand All @@ -958,10 +974,12 @@ function createTaskPty(alias: string, context: GitpodExtensionContext, contextTo
await util.promisify(context.supervisor.terminal.shutdown.bind(context.supervisor.terminal, request, context.supervisor.metadata, {
deadline: Date.now() + context.supervisor.deadlines.short
}))();
context.logger.trace(`${alias} terminal closed`);
} catch (e) {
if (e && e.code === grpc.status.NOT_FOUND) {
// Swallow, the pty has already been killed
} else {
context.logger.error(`${alias} terminal: shutdown failed:`, e);
console.error(`${alias} terminal: shutdown failed:`, e);
}
}
Expand All @@ -985,6 +1003,7 @@ function createTaskPty(alias: string, context: GitpodExtensionContext, contextTo
}))();
} catch (e) {
if (e && e.code !== grpc.status.NOT_FOUND) {
context.logger.error(`${alias} terminal: write failed:`, e);
console.error(`${alias} terminal: write failed:`, e);
}
}
Expand Down Expand Up @@ -1012,6 +1031,7 @@ function createTaskPty(alias: string, context: GitpodExtensionContext, contextTo
}))();
} catch (e) {
if (e && e.code !== grpc.status.NOT_FOUND) {
context.logger.error(`${alias} terminal: resize failed:`, e);
console.error(`${alias} terminal: resize failed:`, e);
}
}
Expand Down Expand Up @@ -1066,7 +1086,7 @@ async function updateIpcHookCli(context: GitpodExtensionContext): Promise<void>
req.end();
});
} catch (e) {
context.output.appendLine('Failed to update gitpod ipc hook cli: ' + e);
context.logger.error('Failed to update gitpod ipc hook cli:', e);
console.error('Failed to update gitpod ipc hook cli:', e);
}
}
2 changes: 1 addition & 1 deletion extensions/gitpod-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,6 @@
"vscode-jsonrpc": "^5.0.1",
"vscode-nls": "^5.0.0",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
"yazl": "^2.5.1"
}
}
Loading