Skip to content

Commit 3995d70

Browse files
committed
[supervisor-frontend] allow IDEs to send metrics
1 parent 65e872b commit 3995d70

File tree

20 files changed

+783
-39
lines changed

20 files changed

+783
-39
lines changed

WORKSPACE.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ defaultArgs:
77
jbMarketplacePublishTrigger: "false"
88
publishToJBMarketplace: true
99
localAppVersion: unknown
10-
codeCommit: c983b520aa04890daa8cb2da3b947a0069716260
10+
codeCommit: 18b3ab300a16e227344695702b351d7bbc04e87c
1111
codeQuality: stable
1212
intellijDownloadUrl: "https://download.jetbrains.com/idea/ideaIU-2022.2.1.tar.gz"
1313
golandDownloadUrl: "https://download.jetbrains.com/go/goland-2022.2.2.tar.gz"
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
*_pb.*ts
2-
*_pb.*js
3-
*_pb_service.*js
4-
*_pb_service.*ts
1+
lib/

components/ide-metrics-api/typescript-grpcweb/BUILD.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ packages:
44
srcs:
55
- package.json
66
- build.sh
7+
- src/**
78
deps:
89
- components/ide-metrics-api:proto
910
env:

components/ide-metrics-api/typescript-grpcweb/package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"version": "0.0.1",
44
"license": "UNLICENSED",
55
"scripts": {
6-
"build": "bash build.sh"
6+
"watch": "tsc --watch",
7+
"build": "bash build.sh && tsc"
78
},
89
"files": [
910
"lib"
@@ -12,6 +13,6 @@
1213
"grpc-web": "^1.3.1"
1314
},
1415
"devDependencies": {
15-
"typescript": "~4.4.2"
16+
"typescript": "^4.8.2"
1617
}
1718
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License-AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { MetricsServicePromiseClient } from "../lib/idemetrics_grpc_web_pb";
8+
import { AddCounterRequest, ObserveHistogramRequest } from "../lib/idemetrics_pb";
9+
10+
export interface IDEMetric {
11+
kind: "counter" | "histogram";
12+
name: string;
13+
labels: Record<string, string>;
14+
value?: number;
15+
}
16+
17+
export function sentMetrics(
18+
client: MetricsServicePromiseClient,
19+
metrics: IDEMetric[],
20+
): Promise<PromiseSettledResult<void>[]> {
21+
return Promise.allSettled(
22+
metrics.map(async (metric) => {
23+
if (metric.kind === "counter") {
24+
const req = new AddCounterRequest();
25+
req.setName(metric.name);
26+
for (const key in metric.labels) {
27+
req.getLabelsMap().set(key, metric.labels[key]);
28+
}
29+
if (metric.value !== undefined) {
30+
req.setValue(metric.value);
31+
}
32+
client.addCounter(req);
33+
} else {
34+
const req = new ObserveHistogramRequest();
35+
req.setName(metric.name);
36+
for (const key in metric.labels) {
37+
req.getLabelsMap().set(key, metric.labels[key]);
38+
}
39+
if (metric.value !== undefined) {
40+
req.setValue(metric.value);
41+
}
42+
await client.observeHistogram(req);
43+
}
44+
}),
45+
);
46+
}

components/ide-metrics-api/typescript-grpcweb/tsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"outDir": "lib",
66
"lib": [
77
"es6",
8-
"esnext.asynciterable"
8+
"esnext.asynciterable",
9+
"ES2020.Promise",
910
],
1011
"strict": true,
1112
"noEmitOnError": false,

components/supervisor/frontend/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"version": "0.0.0",
66
"dependencies": {
77
"@gitpod/gitpod-protocol": "0.1.5",
8-
"@gitpod/supervisor-api-grpc": "0.1.5"
8+
"@gitpod/supervisor-api-grpc": "0.1.5",
9+
"@gitpod/ide-metrics-api-grpcweb": "0.0.1"
910
},
1011
"devDependencies": {
1112
"@babel/core": "^7.10.0",

components/supervisor/frontend/src/ide/ide-metrics-service-client.ts

+19-2
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,30 @@
55
*/
66

77
import { serverUrl } from '../shared/urls';
8+
import { MetricsServicePromiseClient } from '@gitpod/ide-metrics-api-grpcweb/lib/idemetrics_grpc_web_pb';
9+
import { IDEMetric, sentMetrics as doSendMetrics } from '@gitpod/ide-metrics-api-grpcweb/lib/index';
810

911
export enum MetricsName {
1012
SupervisorFrontendClientTotal = "gitpod_supervisor_frontend_client_total",
1113
SupervisorFrontendErrorTotal = "gitpod_supervisor_frontend_error_total"
1214
}
1315

14-
const MetricsUrl = serverUrl.asIDEMetrics().toString();
16+
const metricsUrl = serverUrl.asIDEMetrics().toString();
1517

1618
interface AddCounterParam {
1719
value?: number;
1820
labels?: Record<string, string>;
1921
}
2022

23+
let _client: MetricsServicePromiseClient | undefined;
24+
function getClient(): MetricsServicePromiseClient {
25+
return _client || (_client = new MetricsServicePromiseClient(metricsUrl));
26+
}
27+
2128
export class IDEMetricsServiceClient {
2229

2330
static async addCounter(metricsName: MetricsName, labels?: Record<string, string>, value?: number) : Promise<boolean> {
24-
const url = `${MetricsUrl}/metrics/counter/add/${metricsName}`
31+
const url = `${metricsUrl}/metrics/counter/add/${metricsName}`
2532
const params: AddCounterParam = { value, labels }
2633
try {
2734
const response = await fetch(url, {
@@ -40,4 +47,14 @@ export class IDEMetricsServiceClient {
4047
return false
4148
}
4249
}
50+
51+
static async sendMetrics(metrics: IDEMetric[]): Promise<void> {
52+
try {
53+
const client = getClient();
54+
await doSendMetrics(client, metrics);
55+
} catch (e) {
56+
console.error("failed to send IDE metrics:", e);
57+
}
58+
}
59+
4360
}

components/supervisor/frontend/src/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ const toStop = new DisposableCollection();
128128
//#region gitpod browser telemetry
129129
window.addEventListener("message", async (event) => {
130130
const type = event.data.type;
131+
// TODO(ak) supervisor should not be aware of VS Code, it should be renamed to send_ide_analytics
131132
if (type === "vscode_telemetry") {
132133
const { event: eventName, properties } = event.data;
133134
window.gitpod.service.server.trackEvent({
@@ -141,6 +142,9 @@ const toStop = new DisposableCollection();
141142
},
142143
});
143144
}
145+
if (type === 'send_ide_metrics') {
146+
IDEMetricsServiceClient.sendMetrics(event.data);
147+
}
144148
})
145149
//#endregion
146150

install/installer/cmd/testdata/render/aws-setup/output.golden

+73-3
Original file line numberDiff line numberDiff line change
@@ -3150,7 +3150,8 @@ data:
31503150
{
31513151
"name": "resource",
31523152
"allowValues": [
3153-
"vscode-web-workbench"
3153+
"vscode-web-workbench",
3154+
"unknown"
31543155
],
31553156
"defaultValue": "unknown"
31563157
},
@@ -3168,9 +3169,78 @@ data:
31683169
"name": "gitpod_supervisor_frontend_client_total",
31693170
"help": "Total count of supervisor frontend client",
31703171
"labels": null
3172+
},
3173+
{
3174+
"name": "gitpod_vscode_extension_gallery_operation_total",
3175+
"help": "Total count of extension operations",
3176+
"labels": [
3177+
{
3178+
"name": "source",
3179+
"allowValues": [
3180+
"window",
3181+
"remote-server",
3182+
"unknown"
3183+
],
3184+
"defaultValue": "unknown"
3185+
},
3186+
{
3187+
"name": "operation",
3188+
"allowValues": [
3189+
"install",
3190+
"update",
3191+
"uninstall",
3192+
"unknown"
3193+
],
3194+
"defaultValue": "unknown"
3195+
},
3196+
{
3197+
"name": "status",
3198+
"allowValues": [
3199+
"success",
3200+
"failure",
3201+
"unknown"
3202+
],
3203+
"defaultValue": "unknown"
3204+
}
3205+
]
31713206
}
31723207
],
3173-
"histogramMetrics": []
3208+
"histogramMetrics": [
3209+
{
3210+
"name": "gitpod_vscode_extension_gallery_operation_duration_seconds",
3211+
"help": "Duration of extension operations in seconds",
3212+
"labels": [
3213+
{
3214+
"name": "source",
3215+
"allowValues": [
3216+
"window",
3217+
"remote-server",
3218+
"unknown"
3219+
],
3220+
"defaultValue": "unknown"
3221+
},
3222+
{
3223+
"name": "operation",
3224+
"allowValues": [
3225+
"install",
3226+
"update",
3227+
"uninstall",
3228+
"unknown"
3229+
],
3230+
"defaultValue": "unknown"
3231+
}
3232+
],
3233+
"buckets": [
3234+
0.1,
3235+
0.5,
3236+
1,
3237+
5,
3238+
10,
3239+
15,
3240+
30
3241+
]
3242+
}
3243+
]
31743244
},
31753245
"debug": false,
31763246
"pprof": {
@@ -6828,7 +6898,7 @@ spec:
68286898
template:
68296899
metadata:
68306900
annotations:
6831-
gitpod.io/checksum_config: 3e35ede3647b985d307718989309d2794fdcb8691dd27fb35f538496fb209d79
6901+
gitpod.io/checksum_config: cb6017c6de7bda7350967a24069bff0a149c3cbe80f89e804ecc67414bea12dd
68326902
creationTimestamp: null
68336903
labels:
68346904
app: gitpod

install/installer/cmd/testdata/render/azure-setup/output.golden

+73-3
Original file line numberDiff line numberDiff line change
@@ -3068,7 +3068,8 @@ data:
30683068
{
30693069
"name": "resource",
30703070
"allowValues": [
3071-
"vscode-web-workbench"
3071+
"vscode-web-workbench",
3072+
"unknown"
30723073
],
30733074
"defaultValue": "unknown"
30743075
},
@@ -3086,9 +3087,78 @@ data:
30863087
"name": "gitpod_supervisor_frontend_client_total",
30873088
"help": "Total count of supervisor frontend client",
30883089
"labels": null
3090+
},
3091+
{
3092+
"name": "gitpod_vscode_extension_gallery_operation_total",
3093+
"help": "Total count of extension operations",
3094+
"labels": [
3095+
{
3096+
"name": "source",
3097+
"allowValues": [
3098+
"window",
3099+
"remote-server",
3100+
"unknown"
3101+
],
3102+
"defaultValue": "unknown"
3103+
},
3104+
{
3105+
"name": "operation",
3106+
"allowValues": [
3107+
"install",
3108+
"update",
3109+
"uninstall",
3110+
"unknown"
3111+
],
3112+
"defaultValue": "unknown"
3113+
},
3114+
{
3115+
"name": "status",
3116+
"allowValues": [
3117+
"success",
3118+
"failure",
3119+
"unknown"
3120+
],
3121+
"defaultValue": "unknown"
3122+
}
3123+
]
30893124
}
30903125
],
3091-
"histogramMetrics": []
3126+
"histogramMetrics": [
3127+
{
3128+
"name": "gitpod_vscode_extension_gallery_operation_duration_seconds",
3129+
"help": "Duration of extension operations in seconds",
3130+
"labels": [
3131+
{
3132+
"name": "source",
3133+
"allowValues": [
3134+
"window",
3135+
"remote-server",
3136+
"unknown"
3137+
],
3138+
"defaultValue": "unknown"
3139+
},
3140+
{
3141+
"name": "operation",
3142+
"allowValues": [
3143+
"install",
3144+
"update",
3145+
"uninstall",
3146+
"unknown"
3147+
],
3148+
"defaultValue": "unknown"
3149+
}
3150+
],
3151+
"buckets": [
3152+
0.1,
3153+
0.5,
3154+
1,
3155+
5,
3156+
10,
3157+
15,
3158+
30
3159+
]
3160+
}
3161+
]
30923162
},
30933163
"debug": false,
30943164
"pprof": {
@@ -6662,7 +6732,7 @@ spec:
66626732
template:
66636733
metadata:
66646734
annotations:
6665-
gitpod.io/checksum_config: 3e35ede3647b985d307718989309d2794fdcb8691dd27fb35f538496fb209d79
6735+
gitpod.io/checksum_config: cb6017c6de7bda7350967a24069bff0a149c3cbe80f89e804ecc67414bea12dd
66666736
creationTimestamp: null
66676737
labels:
66686738
app: gitpod

0 commit comments

Comments
 (0)