Skip to content

Commit 0f4d5dc

Browse files
committed
[code-browser] extensions observability
1 parent 81c5061 commit 0f4d5dc

File tree

23 files changed

+6803
-65
lines changed

23 files changed

+6803
-65
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: a6661898efdac3fa0f6bea841044bffe58f502f3
10+
codeCommit: 88ba007f09ee0c500e37f9862e1e1c4fa559495b
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"

components/ide-metrics-api/idemetrics.proto

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ service MetricsService {
2929
message AddCounterRequest {
3030
string name = 1;
3131
map<string, string> labels = 2;
32-
optional int32 value = 3;
32+
int32 value = 3;
3333
}
3434

3535
message AddCounterResponse {}
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

+3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ packages:
22
- name: lib
33
type: yarn
44
srcs:
5+
- src/**
56
- package.json
67
- build.sh
8+
- webpack.config.js
9+
- tsconfig.json
710
deps:
811
- components/ide-metrics-api:proto
912
env:

components/ide-metrics-api/typescript-grpcweb/build.sh

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
#!/bin/bash
2-
# Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2+
# Copyright (c) 2020 Gitpod GmbH. All rights reserved.
33
# Licensed under the GNU Affero General Public License (AGPL).
44
# See License-AGPL.txt in the project root for license information.
55

6-
curl -LsSo /tmp/protoc-gen-grpc-web https://github.com/grpc/grpc-web/releases/download/1.3.1/protoc-gen-grpc-web-1.3.1-linux-x86_64
7-
chmod +x /tmp/protoc-gen-grpc-web
6+
DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)
87

9-
THIRD_PARTY_INCLUDES="${PROTOLOC:-..}"
8+
THIRD_PARTY_INCLUDES=${PROTOLOC:-$DIR/..}
109
if [ ! -d "$THIRD_PARTY_INCLUDES"/third_party/google/api ]; then
1110
echo "missing $THIRD_PARTY_INCLUDES/third_party/google/api"
1211
exit 1
1312
fi
1413

14+
1515
mkdir -p lib
16+
export PROTO_INCLUDE="-I$THIRD_PARTY_INCLUDES/third_party -I /usr/lib/protoc/include"
1617

1718
protoc -I"$THIRD_PARTY_INCLUDES"/third_party -I/usr/lib/protoc/include \
18-
--plugin=protoc-gen-grpc-web=/tmp/protoc-gen-grpc-web \
19-
--js_out=import_style=commonjs:lib \
20-
--grpc-web_out=import_style=commonjs+dts,mode=grpcweb:lib \
19+
--plugin="protoc-gen-ts=$DIR/node_modules/.bin/protoc-gen-ts" \
20+
--js_out="import_style=commonjs,binary:lib" \
21+
--ts_out="service=grpc-web:lib" \
2122
-I"${PROTOLOC:-..}" "${PROTOLOC:-..}"/*.proto
2223

2324
# shellcheck disable=SC2038

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

+12-3
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,25 @@
22
"name": "@gitpod/ide-metrics-api-grpcweb",
33
"version": "0.0.1",
44
"license": "UNLICENSED",
5+
"main": "lib/index.js",
6+
"types": "lib/index.d.ts",
57
"scripts": {
6-
"build": "bash build.sh"
8+
"build": "bash build.sh && webpack"
79
},
810
"files": [
911
"lib"
1012
],
1113
"dependencies": {
12-
"grpc-web": "^1.3.1"
14+
"@improbable-eng/grpc-web": "^0.14.0",
15+
"google-protobuf": "^3.19.1"
1316
},
1417
"devDependencies": {
15-
"typescript": "~4.4.2"
18+
"@types/google-protobuf": "^3.15.5",
19+
"source-map-loader": "^3.0.0",
20+
"ts-loader": "^9.2.2",
21+
"ts-protoc-gen": "^0.13.0",
22+
"typescript": "^4.2.4",
23+
"webpack": "^5.37.1",
24+
"webpack-cli": "^4.7.0"
1625
}
1726
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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+
export * from "../lib/idemetrics_pb";
8+
export * from "../lib/idemetrics_pb_service";
9+
10+
import { MetricsServiceClient } from "../lib/idemetrics_pb_service";
11+
import { AddCounterRequest, ObserveHistogramRequest } from "../lib/idemetrics_pb";
12+
export interface IDEMetric {
13+
kind: "counter" | "histogram";
14+
name: string;
15+
labels: Record<string, string>;
16+
value?: number;
17+
}
18+
19+
export function sendMetrics(client: MetricsServiceClient, metrics: IDEMetric[]): Promise<PromiseSettledResult<void>[]> {
20+
return Promise.allSettled(
21+
metrics.map(async (metric) => {
22+
if (metric.kind === "counter") {
23+
const req = new AddCounterRequest();
24+
req.setName(metric.name);
25+
for (const key in metric.labels) {
26+
req.getLabelsMap().set(key, metric.labels[key]);
27+
}
28+
if (metric.value !== undefined) {
29+
req.setValue(metric.value);
30+
}
31+
await new Promise((resolve, reject) =>
32+
client.addCounter(req, (e) => {
33+
if (e) {
34+
reject(e);
35+
} else {
36+
resolve(undefined);
37+
}
38+
}),
39+
);
40+
} else {
41+
const req = new ObserveHistogramRequest();
42+
req.setName(metric.name);
43+
for (const key in metric.labels) {
44+
req.getLabelsMap().set(key, metric.labels[key]);
45+
}
46+
if (metric.value !== undefined) {
47+
req.setValue(metric.value);
48+
}
49+
await new Promise((resolve, reject) =>
50+
client.observeHistogram(req, (e) => {
51+
if (e) {
52+
reject(e);
53+
} else {
54+
resolve(undefined);
55+
}
56+
}),
57+
);
58+
}
59+
}),
60+
);
61+
}

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

+4-16
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
11
{
22
"compilerOptions": {
3-
"rootDir": "src",
4-
"experimentalDecorators": true,
5-
"outDir": "lib",
3+
"module": "commonjs",
4+
"target": "es6",
65
"lib": [
76
"es6",
8-
"esnext.asynciterable"
7+
"ES2020.Promise"
98
],
10-
"strict": true,
11-
"noEmitOnError": false,
12-
"noUnusedLocals": true,
13-
"emitDecoratorMetadata": true,
14-
"strictPropertyInitialization": false,
15-
"downlevelIteration": true,
16-
"module": "commonjs",
17-
"moduleResolution": "node",
18-
"target": "es6",
19-
"jsx": "react",
9+
"outDir": "lib",
2010
"sourceMap": true,
2111
"declaration": true,
22-
"declarationMap": true,
23-
"skipLibCheck": true,
2412
"useUnknownInCatchVariables": false
2513
},
2614
"include": [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
// @ts-check
8+
const path = require("path");
9+
10+
module.exports = {
11+
entry: "./src/index.ts",
12+
devtool: "source-map",
13+
module: {
14+
rules: [
15+
{
16+
test: /\.ts$/,
17+
loader: "ts-loader",
18+
},
19+
{
20+
test: /\.js$/,
21+
use: ["source-map-loader"],
22+
enforce: "pre",
23+
exclude: /node_modules/,
24+
},
25+
],
26+
},
27+
output: {
28+
filename: "index.js",
29+
path: path.resolve("./lib"),
30+
libraryTarget: "umd",
31+
globalObject: "typeof self !== 'undefined' ? self : this",
32+
},
33+
externals: {
34+
"@improbable-eng/grpc-web": "commonjs2 @improbable-eng/grpc-web",
35+
},
36+
mode: "production",
37+
};

components/supervisor/frontend/src/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ window.addEventListener('error', (event) => {
2424
// If the event has a `target`, it means that it wasn't a script error
2525
if (resourceSource) {
2626
if (resourceSource.match(new RegExp(/\/build\/ide\/code:.+\/__files__\//g))) {
27+
// TODO(ak) reconsider how to hide knowledge of VS Code from supervisor frontend, i.e instrument amd loader instead
2728
labels['resource'] = 'vscode-web-workbench';
2829
}
2930
labels['error'] = 'LoadError';
@@ -126,6 +127,10 @@ const toStop = new DisposableCollection();
126127
toStop.push({ dispose: () => window.removeEventListener('message', hideDesktopIdeEventListener) });
127128

128129
//#region gitpod browser telemetry
130+
// TODO(ak) get rid of it
131+
// it is bad usage of window.postMessage
132+
// VS Code should use Segment directly here and publish to production/staging untrusted
133+
// supervisor frontend should not care about IDE specifics
129134
window.addEventListener("message", async (event) => {
130135
const type = event.data.type;
131136
if (type === "vscode_telemetry") {

0 commit comments

Comments
 (0)