Skip to content

Commit 3a599ac

Browse files
committed
Add export logs contribution
1 parent 437b823 commit 3a599ac

File tree

10 files changed

+194
-5
lines changed

10 files changed

+194
-5
lines changed

build/.webignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,6 @@ xterm-addon-webgl/out/**
4545

4646
browser-headers/**
4747
google-protobuf/**
48+
49+
@zip.js/**
50+
[email protected]/zip.js/dist/zip-no-worker-deflate.min.js

extensions/gitpod-web/src/extension.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ export async function activate(context: vscode.ExtensionContext) {
3131
if (!gitpodContext) {
3232
return;
3333
}
34-
registerDesktop(gitpodContext);
34+
35+
logContextInfo(gitpodContext);
36+
37+
registerDesktop();
3538
registerAuth(gitpodContext);
3639
registerPorts(gitpodContext);
3740
registerTasks(gitpodContext, (options, parentTerminal) => {
@@ -64,6 +67,14 @@ export function deactivate() {
6467
return gitpodContext.dispose();
6568
}
6669

70+
function logContextInfo(context: GitpodExtensionContext) {
71+
const output = context.output;
72+
73+
output.appendLine(`GITPOD_WORKSPACE_CONTEXT_URL: ${context.info.getWorkspaceContextUrl()}`);
74+
output.appendLine(`GITPOD_INSTANCE_ID: ${context.info.getInstanceId()}`);
75+
output.appendLine(`GITPOD_WORKSPACE_URL: ${context.info.getWorkspaceUrl()}`);
76+
}
77+
6778
export function registerAuth(context: GitpodExtensionContext): void {
6879
type Keytar = {
6980
getPassword: typeof keytarType['getPassword'];
@@ -1196,7 +1207,7 @@ export function registerExtensionManagement(context: GitpodExtensionContext): vo
11961207
context.subscriptions.push(vscode.extensions.onDidChange(() => validateGitpodFile()));
11971208
}
11981209

1199-
export async function registerDesktop(_: GitpodExtensionContext): Promise<void> {
1210+
async function registerDesktop(): Promise<void> {
12001211
const config = vscode.workspace.getConfiguration('gitpod.openInStable');
12011212
if (config.get<boolean>('neverPrompt') === true) {
12021213
return;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"@vscode/sqlite3": "5.0.8",
7171
"@vscode/sudo-prompt": "9.3.1",
7272
"@vscode/vscode-languagedetection": "1.0.21",
73+
"@zip.js/zip.js": "^2.4.6",
7374
"applicationinsights": "1.4.2",
7475
"graceful-fs": "4.2.8",
7576
"http-proxy-agent": "^2.1.0",

remote/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"@microsoft/applicationinsights-web": "^2.6.4",
88
"@vscode/iconv-lite-umd": "0.7.0",
99
"@vscode/vscode-languagedetection": "1.0.21",
10+
"@zip.js/zip.js": "^2.4.6",
1011
"jschardet": "3.0.0",
1112
"tas-client-umd": "0.1.4",
1213
"vscode-oniguruma": "1.6.1",

remote/web/yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@
123123
resolved "https://registry.yarnpkg.com/@vscode/vscode-languagedetection/-/vscode-languagedetection-1.0.21.tgz#89b48f293f6aa3341bb888c1118d16ff13b032d3"
124124
integrity sha512-zSUH9HYCw5qsCtd7b31yqkpaCU6jhtkKLkvOOA8yTrIRfBSOFb8PPhgmMicD7B/m+t4PwOJXzU1XDtrM9Fd3/g==
125125

126+
"@zip.js/zip.js@^2.4.6":
127+
version "2.4.6"
128+
resolved "https://registry.yarnpkg.com/@zip.js/zip.js/-/zip.js-2.4.6.tgz#eb284910f4dcbccb267c5ef76950fb84ee43bb74"
129+
integrity sha512-gP13tvMy1bhaTWw5I/Sm3mJAOU7J8S18e4sAcscGzYY8NVUF8FRirfY17eYq+rZhRBk8SNg5bFzzWgFR47qSyw==
130+
126131
browser-headers@^0.4.1:
127132
version "0.4.1"
128133
resolved "https://registry.yarnpkg.com/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02"
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/* eslint-disable code-import-patterns */
2+
/* eslint-disable header/header */
3+
/*---------------------------------------------------------------------------------------------
4+
* Copyright (c) Gitpod. All rights reserved.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
8+
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
9+
import { IFileService } from 'vs/platform/files/common/files';
10+
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
11+
import { CATEGORIES } from 'vs/workbench/common/actions';
12+
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
13+
import { URI } from 'vs/base/common/uri';
14+
import * as resources from 'vs/base/common/resources';
15+
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
16+
import { CancellationTokenSource } from 'vs/base/common/cancellation';
17+
import type * as zipModule from '@zip.js/zip.js';
18+
import { Schemas } from 'vs/base/common/network';
19+
import { triggerDownload } from 'vs/base/browser/dom';
20+
21+
const getZipModule = (function () {
22+
let zip: typeof zipModule;
23+
return async () => {
24+
if (!zip) {
25+
// when actually importing the module change `zip.js` to `zipjs`
26+
// without the dot because loader.js will do a check for `.js` extension
27+
// and it won't resolve the module path correctly
28+
// @ts-ignore
29+
zip = await import('@zip.js/zipjs');
30+
zip.configure({
31+
useWebWorkers: false
32+
});
33+
}
34+
return zip;
35+
};
36+
})();
37+
38+
registerAction2(class ExportLogsAction extends Action2 {
39+
constructor() {
40+
super({
41+
id: 'gitpod.workbench.exportLogs',
42+
title: { original: 'Export all logs', value: 'Export all logs' },
43+
category: CATEGORIES.Developer,
44+
menu: {
45+
id: MenuId.CommandPalette
46+
}
47+
});
48+
}
49+
50+
async run(accessor: ServicesAccessor): Promise<void> {
51+
const progressService = accessor.get(IProgressService);
52+
const fileService = accessor.get(IFileService);
53+
const environmentService = accessor.get(IBrowserWorkbenchEnvironmentService);
54+
const remoteAgentService = accessor.get(IRemoteAgentService);
55+
56+
const cts = new CancellationTokenSource();
57+
const bufferData = await progressService.withProgress<Uint8Array | undefined>(
58+
{
59+
location: ProgressLocation.Dialog,
60+
title: 'Exporting logs to zip file ...',
61+
cancellable: true,
62+
delay: 1000
63+
},
64+
async progress => {
65+
const token = cts.token;
66+
67+
const zip = await getZipModule();
68+
const uint8ArrayWriter = new zip.Uint8ArrayWriter();
69+
const writer = new zip.ZipWriter(uint8ArrayWriter);
70+
71+
if (token.isCancellationRequested) {
72+
return undefined;
73+
}
74+
75+
const entries: { name: string; resource: URI }[] = [];
76+
const logsPath = URI.file(environmentService.logsPath).with({ scheme: environmentService.logFile.scheme });
77+
const stat = await fileService.resolve(logsPath);
78+
if (stat.children) {
79+
entries.push(...stat.children.filter(stat => !stat.isDirectory).map(stat => ({ name: resources.basename(stat.resource), resource: stat.resource })));
80+
}
81+
82+
if (token.isCancellationRequested) {
83+
return undefined;
84+
}
85+
86+
const remoteEnv = await remoteAgentService.getEnvironment();
87+
const remoteLogsPath = remoteEnv?.logsPath;
88+
if (remoteLogsPath) {
89+
const remoteAgentLogFile = resources.joinPath(remoteLogsPath, 'remoteagent.log');
90+
if (await fileService.exists(remoteAgentLogFile)) {
91+
entries.push({ name: resources.basename(remoteAgentLogFile), resource: remoteAgentLogFile });
92+
}
93+
}
94+
95+
if (token.isCancellationRequested) {
96+
return undefined;
97+
}
98+
99+
const remoteExtHostLogsPath = remoteEnv?.extensionHostLogsPath;
100+
if (remoteExtHostLogsPath) {
101+
const remoteExtHostLogsFile = resources.joinPath(remoteExtHostLogsPath, 'exthost.log');
102+
if (await fileService.exists(remoteExtHostLogsFile)) {
103+
entries.push({ name: resources.basename(remoteExtHostLogsFile), resource: remoteExtHostLogsFile });
104+
}
105+
106+
let stat = await fileService.resolve(remoteExtHostLogsPath);
107+
if (stat.children) {
108+
const ouputLoggingDirs = stat.children.filter(stat => stat.isDirectory);
109+
for (const outLogDir of ouputLoggingDirs) {
110+
if (token.isCancellationRequested) {
111+
return undefined;
112+
}
113+
114+
stat = await fileService.resolve(outLogDir.resource);
115+
if (stat.children) {
116+
entries.push(...stat.children.filter(stat => !stat.isDirectory).map(stat => ({
117+
name: `${resources.basename(outLogDir.resource)}_${resources.basename(stat.resource)}`,
118+
resource: stat.resource
119+
})));
120+
}
121+
}
122+
}
123+
}
124+
125+
if (token.isCancellationRequested) {
126+
return undefined;
127+
}
128+
129+
const credentialHelperPath = URI.file('/tmp/gitpod-git-credential-helper.log').with({ scheme: Schemas.vscodeRemote });
130+
if (await fileService.exists(credentialHelperPath)) {
131+
entries.push({ name: resources.basename(credentialHelperPath), resource: credentialHelperPath });
132+
}
133+
134+
console.log('All log entries', entries);
135+
136+
for (const entry of entries) {
137+
if (token.isCancellationRequested) {
138+
return undefined;
139+
}
140+
const content = await fileService.readFile(entry.resource, { atomic: true }, token);
141+
142+
if (token.isCancellationRequested) {
143+
return undefined;
144+
}
145+
await writer.add(entry.name, new zip.Uint8ArrayReader(content.value.buffer));
146+
}
147+
148+
return writer.close();
149+
},
150+
() => cts.dispose(true)
151+
);
152+
153+
if (bufferData) {
154+
triggerDownload(bufferData, 'vscodeLogs.zip');
155+
}
156+
}
157+
});

src/vs/gitpod/browser/workbench/workbench-dev.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@
5353
}),
5454
paths: {
5555
...self.webPackagePaths,
56-
'@gitpod/local-app-api-grpcweb': `${window.location.origin}/static/node_modules/@gitpod/local-app-api-grpcweb/lib/localapp.js`,
57-
'@improbable-eng/grpc-web': `${window.location.origin}/static/node_modules/@improbable-eng/grpc-web/dist/grpc-web-client.umd.js`
56+
'@gitpod/local-app-api-grpcweb': `${window.location.origin}/static/remote/web/node_modules/@gitpod/local-app-api-grpcweb/lib/localapp.js`,
57+
'@improbable-eng/grpc-web': `${window.location.origin}/static/remote/web/node_modules/@improbable-eng/grpc-web/dist/grpc-web-client.umd.js`,
58+
'@zip.js/zipjs': `${window.location.origin}/static/remote/web/node_modules/@zip.js/zip.js/dist/zip-no-worker-deflate.min.js`
5859
}
5960
});
6061
</script>

src/vs/gitpod/browser/workbench/workbench.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454
paths: {
5555
...self.webPackagePaths,
5656
'@gitpod/local-app-api-grpcweb': `${window.location.origin}/static/node_modules/@gitpod/local-app-api-grpcweb/lib/localapp.js`,
57-
'@improbable-eng/grpc-web': `${window.location.origin}/static/node_modules/@improbable-eng/grpc-web/dist/grpc-web-client.umd.js`
57+
'@improbable-eng/grpc-web': `${window.location.origin}/static/node_modules/@improbable-eng/grpc-web/dist/grpc-web-client.umd.js`,
58+
'@zip.js/zipjs': `${window.location.origin}/static/node_modules/@zip.js/zip.js/dist/zip-no-worker-deflate.min.js`
5859
}
5960
});
6061
</script>

src/vs/workbench/workbench.web.main.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ import 'vs/workbench/contrib/splash/browser/splash.contribution';
153153
// Offline
154154
import 'vs/workbench/contrib/offline/browser/offline.contribution';
155155

156+
// Gitpod: Export Logs command
157+
// eslint-disable-next-line code-import-patterns
158+
import 'vs/gitpod/browser/workbench/contrib/exportLogs.contribution';
159+
156160
//#endregion
157161

158162

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,11 @@
21162116
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
21172117
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
21182118

2119+
"@zip.js/zip.js@^2.4.6":
2120+
version "2.4.6"
2121+
resolved "https://registry.yarnpkg.com/@zip.js/zip.js/-/zip.js-2.4.6.tgz#eb284910f4dcbccb267c5ef76950fb84ee43bb74"
2122+
integrity sha512-gP13tvMy1bhaTWw5I/Sm3mJAOU7J8S18e4sAcscGzYY8NVUF8FRirfY17eYq+rZhRBk8SNg5bFzzWgFR47qSyw==
2123+
21192124
abbrev@1:
21202125
version "1.1.1"
21212126
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"

0 commit comments

Comments
 (0)