Skip to content

Commit

Permalink
add ws client metrics (#18773)
Browse files Browse the repository at this point in the history
  • Loading branch information
akosyakov authored Sep 22, 2023
1 parent bee03a1 commit 3444343
Show file tree
Hide file tree
Showing 15 changed files with 292 additions and 107 deletions.
6 changes: 5 additions & 1 deletion components/dashboard/BUILD.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ packages:
- "src/**/*.svg"
- "src/**/*.png"
- "src/**/*.webp"
- "src/**/*.json"
- "typings/**"
- package.json
- tailwind.config.js
Expand All @@ -21,7 +22,10 @@ packages:
- components/public-api/typescript:lib
config:
commands:
build: ["yarn", "build"]
build:
- sh
- -c
- yq w -i src/service/config.json commit commit-${__git_commit} -j && yarn build
test: ["yarn", "test:unit"]
yarnLock: ${coreYarnLockBase}/yarn.lock
dontTest: false
Expand Down
3 changes: 3 additions & 0 deletions components/dashboard/src/service/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"commit": "<this value will insert by leeway before running tsc/webpack>"
}
28 changes: 15 additions & 13 deletions components/dashboard/src/service/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@ import { GitpodHostUrl } from "@gitpod/gitpod-protocol/lib/util/gitpod-host-url"
import { MetricsReporter } from "@gitpod/public-api/lib/metrics";
import { getExperimentsClient } from "../experiments/client";
import { v4 } from "uuid";
const commit = require("./config.json").commit;

const originalConsoleError = console.error;

const options = {
const metricsReporter = new MetricsReporter({
gitpodUrl: new GitpodHostUrl(window.location.href).withoutWorkspacePrefix().toString(),
clientName: "dashboard",
clientVersion: "",
logError: originalConsoleError.bind(console),
clientVersion: commit,
log: {
error: originalConsoleError.bind(console),
debug: console.debug.bind(console),
},
isEnabled: () => getExperimentsClient().getValueAsync("dashboard_metrics_enabled", false, {}),
};
fetch("/api/version").then(async (res) => {
const version = await res.text();
options.clientVersion = version;
commonErrorDetails: {
sessionId: v4(),
},
});
const metricsReporter = new MetricsReporter(options);
metricsReporter.startReporting();

window.addEventListener("unhandledrejection", (event) => {
Expand All @@ -41,11 +43,12 @@ console.error = function (...args) {
reportError(...args);
};

const commonDetails = {
sessionId: v4(),
};
export function updateCommonErrorDetails(update: { [key: string]: string | undefined }) {
Object.assign(commonDetails, update);
metricsReporter.updateCommonErrorDetails(update);
}

export function instrumentWebSocket(ws: WebSocket, origin: string) {
metricsReporter.instrumentWebSocket(ws, origin);
}

export function reportError(...args: any[]) {
Expand Down Expand Up @@ -88,7 +91,6 @@ export function reportError(...args: any[]) {
),
);
}
data = Object.assign(data, commonDetails);

if (err) {
metricsReporter.reportError(err, data);
Expand Down
44 changes: 38 additions & 6 deletions components/dashboard/src/service/service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ import { IDEFrontendDashboardService } from "@gitpod/gitpod-protocol/lib/fronten
import { RemoteTrackMessage } from "@gitpod/gitpod-protocol/lib/analytics";
import { helloService } from "./public-api";
import { getExperimentsClient } from "../experiments/client";
import { ConnectError, Code } from "@bufbuild/connect";
import { instrumentWebSocket } from "./metrics";

export const gitpodHostUrl = new GitpodHostUrl(window.location.toString());

function createGitpodService<C extends GitpodClient, S extends GitpodServer>() {
let host = gitpodHostUrl.asWebsocket().with({ pathname: GitpodServerPath }).withApi();

const connectionProvider = new WebSocketConnectionProvider();
instrumentWebSocketConnection(connectionProvider);
let numberOfErrors = 0;
let onReconnect = () => {};
const proxy = connectionProvider.createProxy<S>(host.toString(), undefined, {
Expand All @@ -51,6 +54,23 @@ function createGitpodService<C extends GitpodClient, S extends GitpodServer>() {
return new GitpodServiceImpl<C, S>(proxy, { onReconnect });
}

function instrumentWebSocketConnection(connectionProvider: WebSocketConnectionProvider): void {
const originalCreateWebSocket = connectionProvider["createWebSocket"];
connectionProvider["createWebSocket"] = (url: string) => {
return originalCreateWebSocket.call(
connectionProvider,
url,
new Proxy(WebSocket, {
construct(target: any, argArray) {
const webSocket = new target(...argArray);
instrumentWebSocket(webSocket, "gitpod");
return webSocket;
},
}),
);
};
}

export function getGitpodService(): GitpodService {
const w = window as any;
const _gp = w._gp || (w._gp = {});
Expand Down Expand Up @@ -125,16 +145,28 @@ function testPublicAPI(service: any): void {
if (isTest) {
try {
let previousCount = 0;
for await (const reply of helloService.lotsOfReplies({ previousCount })) {
for await (const reply of helloService.lotsOfReplies(
{ previousCount },
{
// GCP timeout is 10 minutes, we timeout 3 mins earlier
// to avoid unknown network errors
timeoutMs: 7 * 60 * 1000,
},
)) {
previousCount = reply.count;
backoff = BASE_BACKOFF;
}
} catch (e) {
console.error(e, {
userId: user?.id,
grpcType,
});
backoff = Math.min(2 * backoff, MAX_BACKOFF);
if (ConnectError.from(e).code === Code.Canceled) {
// timeout is expected, continue as usual
backoff = BASE_BACKOFF;
} else {
backoff = Math.min(2 * backoff, MAX_BACKOFF);
console.error(e, {
userId: user?.id,
grpcType,
});
}
}
} else {
backoff = BASE_BACKOFF;
Expand Down
25 changes: 0 additions & 25 deletions components/gitpod-protocol/src/gitpod-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ import {
WorkspaceInstanceRepoStatus,
} from "./workspace-instance";
import { AdminServer } from "./admin-protocol";
import { GitpodHostUrl } from "./util/gitpod-host-url";
import { WebSocketConnectionProvider } from "./messaging/browser/connection";
import { Emitter } from "./util/event";
import { RemotePageMessage, RemoteTrackMessage, RemoteIdentifyMessage } from "./analytics";
import { IDEServer } from "./ide-protocol";
Expand Down Expand Up @@ -712,26 +710,3 @@ export class GitpodServiceImpl<Client extends GitpodClient, Server extends Gitpo
}
}
}

export function createGitpodService<C extends GitpodClient, S extends GitpodServer>(
serverUrl: string | Promise<string>,
) {
const toWsUrl = (serverUrl: string) => {
return new GitpodHostUrl(serverUrl).asWebsocket().withApi({ pathname: GitpodServerPath }).toString();
};
let url: string | Promise<string>;
if (typeof serverUrl === "string") {
url = toWsUrl(serverUrl);
} else {
url = serverUrl.then((url) => toWsUrl(url));
}

const connectionProvider = new WebSocketConnectionProvider();
let onReconnect = () => {};
const gitpodServer = connectionProvider.createProxy<S>(url, undefined, {
onListening: (socket) => {
onReconnect = () => socket.reconnect();
},
});
return new GitpodServiceImpl<C, S>(gitpodServer, { onReconnect });
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,14 @@ export class WebSocketConnectionProvider {
/**
* Creates a web socket for the given url
*/
createWebSocket(url: string): WebSocket {
createWebSocket(url: string, WebSocketConstructor = WebSocket): WebSocket {
return new ReconnectingWebSocket(url, undefined, {
maxReconnectionDelay: 10000,
minReconnectionDelay: 1000,
reconnectionDelayGrowFactor: 1.3,
maxRetries: Infinity,
debug: false,
WebSocket: WebSocket,
WebSocket: WebSocketConstructor,
}) as any;
}
}
Expand Down
Loading

0 comments on commit 3444343

Please sign in to comment.