Skip to content

extensions observability #422

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

Merged
merged 1 commit into from
Sep 5, 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
9 changes: 8 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,14 @@
"presentation": {
"group": "0_vscode",
"order": 2
}
},
"env": {
"VSCODE_DEV": "1",
"NODE_ENV": "development"
},
"args": [
"--without-connection-token"
]
},
{
"type": "node",
Expand Down
1 change: 1 addition & 0 deletions build/.webignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ xterm-addon-webgl/out/**

@gitpod/**
!@gitpod/local-app-api-grpcweb/lib/localapp.js
!@gitpod/ide-metrics-api-grpcweb/lib/index.js

browser-headers/**
google-protobuf/**
Expand Down
31 changes: 31 additions & 0 deletions doc/DEV.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## Observability

### Metrics defintion
- Declare new metrics or update existing in https://github.com/gitpod-io/gitpod/blob/ad355c4d9abd858a44daf15f9bd6747976142911/install/installer/pkg/components/ide-metrics/configmap.go
- Create a new branch and push, wait for https://werft.gitpod-dev.com/ to create a preview env.

### Collecting metrics
- Convert VS Code telemetry to metrics in https://github.com/gitpod-io/openvscode-server/blob/63796b8c6eca9bcaf36b90ae1e96dae32638bab6/src/vs/gitpod/common/insightsHelper.ts#L35.

### Testing from sources
- Add to product.json (don't commit!):
```jsonc
"gitpodPreview": {
"host": "<host of preview env>",
// optionally to log to stdout or browser console
"log": {
"metrics": true,
"analytics": false,
}
}
```
- Restart VS Code Server and open VS Code preview page to trigger telemetry events.
- In dev workspace for gitpod-io/gitpod run `./dev/preview/portforward-monitoring-satellite.sh -c harvester`
- Navigate to a printed Grafana link, open Explorer view, select prometheus as a data source and query for metrics.

### Integration testing

- Commit changes in this repo.
- Update codeCommit in WORKSPACE.yaml in gitpod-io/gitpod and push.
- Wait for https://werft.gitpod-dev.com/ to update preview envs.
- Test the complete integration.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@
},
"dependencies": {
"@gitpod/gitpod-protocol": "main",
"@gitpod/ide-metrics-api-grpcweb": "ak-ext-metrics",
"@gitpod/local-app-api-grpcweb": "main",
"@gitpod/supervisor-api-grpc": "main",
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
"@microsoft/1ds-core-js": "^3.2.2",
"@microsoft/1ds-post-js": "^3.2.2",
"@parcel/watcher": "2.0.5",
Expand Down
2 changes: 2 additions & 0 deletions remote/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"private": true,
"dependencies": {
"@gitpod/gitpod-protocol": "main",
"@gitpod/ide-metrics-api-grpcweb": "ak-ext-metrics",
"@gitpod/supervisor-api-grpc": "main",
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
"@microsoft/1ds-core-js": "^3.2.2",
"@microsoft/1ds-post-js": "^3.2.2",
"@parcel/watcher": "2.0.5",
Expand Down
1 change: 1 addition & 0 deletions remote/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"@gitpod/local-app-api-grpcweb": "main",
"@gitpod/ide-metrics-api-grpcweb": "ak-ext-metrics",
"@microsoft/1ds-core-js": "^3.2.2",
"@microsoft/1ds-post-js": "^3.2.2",
"@vscode/iconv-lite-umd": "0.7.0",
Expand Down
13 changes: 13 additions & 0 deletions remote/web/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
# yarn lockfile v1


"@gitpod/ide-metrics-api-grpcweb@ak-ext-metrics":
version "0.0.1-ak-ext-metrics.4"
resolved "https://registry.yarnpkg.com/@gitpod/ide-metrics-api-grpcweb/-/ide-metrics-api-grpcweb-0.0.1-ak-ext-metrics.4.tgz#9dacee7f13181e132fba9e4a5b97cb7f4b1739d2"
integrity sha512-s1C4W5Q7nlgyaQGCKqG8gI1ZdzwsaFZW2k8VX5hJKIcpD5S60I7AJbP1wVxYhRqR93YW3++DHydSpbjBUVnQFA==
dependencies:
"@improbable-eng/grpc-web" "^0.14.0"
google-protobuf "^3.19.1"

"@gitpod/local-app-api-grpcweb@main":
version "0.1.5-main.1701"
resolved "https://registry.yarnpkg.com/@gitpod/local-app-api-grpcweb/-/local-app-api-grpcweb-0.1.5-main.1701.tgz#3f4f4203c4532b098d697c65799095c3d4add9d4"
Expand Down Expand Up @@ -93,6 +101,11 @@ google-protobuf@^3.17.0:
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.19.0.tgz#97f474323c92f19fd6737af1bb792e396991e0b8"
integrity sha512-qXGAiv3OOlaJXJNeKOBKxbBAwjsxzhx+12ZdKOkZTsqsRkyiQRmr/nBkAkqnuQ8cmA9X5NVXvObQTpHVnXE2DQ==

google-protobuf@^3.19.1:
version "3.21.0"
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.0.tgz#8dfa3fca16218618d373d414d3c1139e28034d6e"
integrity sha512-byR7MBTK4tZ5PZEb+u5ZTzpt4SfrTxv5682MjPlHN16XeqgZE2/8HOIWeiXe8JKnT9OVbtBGhbq8mtvkK8cd5g==

[email protected]:
version "3.0.0"
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882"
Expand Down
25 changes: 25 additions & 0 deletions remote/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@
vscode-ws-jsonrpc "^0.2.0"
ws "^7.4.6"

"@gitpod/ide-metrics-api-grpcweb@ak-ext-metrics":
version "0.0.1-ak-ext-metrics.4"
resolved "https://registry.yarnpkg.com/@gitpod/ide-metrics-api-grpcweb/-/ide-metrics-api-grpcweb-0.0.1-ak-ext-metrics.4.tgz#9dacee7f13181e132fba9e4a5b97cb7f4b1739d2"
integrity sha512-s1C4W5Q7nlgyaQGCKqG8gI1ZdzwsaFZW2k8VX5hJKIcpD5S60I7AJbP1wVxYhRqR93YW3++DHydSpbjBUVnQFA==
dependencies:
"@improbable-eng/grpc-web" "^0.14.0"
google-protobuf "^3.19.1"

"@gitpod/supervisor-api-grpc@main":
version "0.1.5-main.2046"
resolved "https://registry.yarnpkg.com/@gitpod/supervisor-api-grpc/-/supervisor-api-grpc-0.1.5-main.2046.tgz#47b450cda80b3b655a76e2829a8eca66d70084bc"
Expand Down Expand Up @@ -63,6 +71,18 @@
protobufjs "^6.10.0"
yargs "^16.1.1"

"@improbable-eng/grpc-web-node-http-transport@^0.15.0":
version "0.15.0"
resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.15.0.tgz#5a064472ef43489cbd075a91fb831c2abeb09d68"
integrity sha512-HLgJfVolGGpjc9DWPhmMmXJx8YGzkek7jcCFO1YYkSOoO81MWRZentPOd/JiKiZuU08wtc4BG+WNuGzsQB5jZA==

"@improbable-eng/grpc-web@^0.14.0":
version "0.14.1"
resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz#f4662f64dc89c0f956a94bb8a3b576556c74589c"
integrity sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==
dependencies:
browser-headers "^0.4.1"

"@microsoft/[email protected]", "@microsoft/1ds-core-js@^3.2.2":
version "3.2.3"
resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz#2217d92ec8b073caa4577a13f40ea3a5c4c4d4e7"
Expand Down Expand Up @@ -358,6 +378,11 @@ bluebird@^3.3.3:
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==

browser-headers@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02"
integrity sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==

buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
Expand Down
10 changes: 10 additions & 0 deletions src/vs/base/common/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ export interface IProductConfiguration {
readonly 'editSessions.store'?: Omit<ConfigurationSyncStore, 'insidersUrl' | 'stableUrl'>;

readonly darwinUniversalAssetId?: string;

readonly gitpodPreview?: IGitpodPreviewConfiguration;
}

export interface IGitpodPreviewConfiguration {
host: string;
log?: {
analytics?: boolean;
metrics?: boolean;
};
}

export type ImportantExtensionTip = { name: string; languages?: string[]; pattern?: string; isExtensionPack?: boolean; whenNotInstalled?: string[] };
Expand Down
97 changes: 86 additions & 11 deletions src/vs/gitpod/browser/gitpodInsightsAppender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@

import { IProductService } from 'vs/platform/product/common/productService';
import { ITelemetryAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { mapTelemetryData, SenderKind } from 'vs/gitpod/common/insightsHelper';
import { mapMetrics, mapTelemetryData } from 'vs/gitpod/common/insightsHelper';
import type { IDEMetric } from '@gitpod/ide-metrics-api-grpcweb';

type SendMetrics = (metrics: IDEMetric[]) => Promise<void>;

export class GitpodInsightsAppender implements ITelemetryAppender {
private _baseProperties: { appName: string; uiKind: 'web'; version: string };
private readonly _baseProperties: { appName: string; uiKind: 'web'; version: string };
private readonly devMode = this.productService.nameShort.endsWith(' Dev');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look nice, should be moved to workbench.ts and if true then set gitpodPreview to undefined and use that as a check here

constructor(
@IProductService private readonly productService: IProductService
) {

this._baseProperties = {
appName: this.productService.nameShort,
uiKind: 'web',
Expand All @@ -22,15 +25,87 @@ export class GitpodInsightsAppender implements ITelemetryAppender {
}

public log(eventName: string, data: any): void {
const trackMessage = mapTelemetryData(SenderKind.Browser, eventName, data);
if (!trackMessage) {
return;
this.sendAnalytics(eventName, data);
this.sendMetrics(eventName, data);
}

private sendAnalytics(eventName: string, data: any): void {
try {
const trackMessage = mapTelemetryData('window', eventName, data);
if (!trackMessage) {
return;
}
trackMessage.properties = {
...trackMessage.properties,
...this._baseProperties,
};
if (this.devMode) {
if (this.productService.gitpodPreview?.log?.analytics) {
console.log('Gitpod Analytics: ', JSON.stringify(trackMessage, undefined, 2));
}
} else {
// TODO(ak) get rid of it
// it is bad usage of window.postMessage
// we should use Segment directly here and publish to production/staging untrusted
// use server api to resolve a user
window.postMessage({ type: 'vscode_telemetry', event: trackMessage.event, properties: trackMessage.properties }, '*');
}
} catch (e) {
console.error('failed to send IDE analytic:', e);
}
trackMessage.properties = {
...trackMessage.properties,
...this._baseProperties,
};
window.postMessage({ type: 'vscode_telemetry', event: trackMessage.event, properties: trackMessage.properties }, '*');
}

private async sendMetrics(eventName: string, data: any): Promise<void> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The browser gitpodInsightsAppender.ts is just and edge for the reconnection events when we lose connection to the remote server, all other events will be send to the remote so not sure if we need the sendMetrics logic here

try {
const metrics = mapMetrics('window', eventName, data);
if (!metrics || !metrics.length) {
return;
}
if (this.devMode) {
if (this.productService.gitpodPreview?.log?.metrics) {
console.log('Gitpod Metrics: ', JSON.stringify(metrics, undefined, 2));
}
}
const doSendMetrics = await this.getSendMetrics();
if (doSendMetrics) {
await doSendMetrics(metrics);
}
} catch (e) {
console.error('failed to send IDE metric:', e);
}
}

private _sendMetrics: Promise<SendMetrics | undefined> | undefined;
private getSendMetrics(): Promise<SendMetrics | undefined> {
if (this._sendMetrics) {
return this._sendMetrics;
}
return this._sendMetrics = (async () => {
let gitpodHost: string | undefined;
if (!this.devMode) {
const infoResponse = await fetch(window.location.protocol + '//' + window.location.host + '/_supervisor/v1/info/workspace', {
credentials: 'include'
});
if (!infoResponse.ok) {
throw new Error(`Getting workspace info failed: ${infoResponse.statusText}`);
}
const info: { gitpodHost: string } = await infoResponse.json();
gitpodHost = new URL(info.gitpodHost).host;
} else if (this.productService.gitpodPreview) {
gitpodHost = this.productService.gitpodPreview.host;
}
if (!gitpodHost) {
return undefined;
}
// load grpc-web before see https://github.com/gitpod-io/gitpod/issues/4448
await import('@improbable-eng/grpc-web');
const { MetricsServiceClient, sendMetrics } = await import('@gitpod/ide-metrics-api-grpcweb');
const ideMetricsEndpoint = 'https://ide.' + gitpodHost + '/metrics-api';
const client = new MetricsServiceClient(ideMetricsEndpoint);
return async (metrics: IDEMetric[]) => {
await sendMetrics(client, metrics);
};
})();
}

public flush(): Promise<any> {
Expand Down
Loading