Skip to content

Commit 3cf0cf2

Browse files
authored
[dashboard] unify error reporting (#18726)
* [dashboard] unify error reporting move error boundary to general error reporting endpoint as well * add user to common details * fix common properties in metrics
1 parent 4ac15c7 commit 3cf0cf2

File tree

6 files changed

+45
-45
lines changed

6 files changed

+45
-45
lines changed

components/dashboard/src/components/error-boundaries/ReloadPageErrorBoundary.tsx

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
*/
66

77
import { FC, useCallback } from "react";
8-
import { ErrorBoundary, FallbackProps, ErrorBoundaryProps } from "react-error-boundary";
8+
import { ErrorBoundary, ErrorBoundaryProps, FallbackProps } from "react-error-boundary";
99
import gitpodIcon from "../../icons/gitpod.svg";
10-
import { getGitpodService } from "../../service/service";
1110
import { Heading1, Subheading } from "../typography/headings";
11+
import { reportError } from "../../service/metrics";
1212

1313
export type CaughtError = Error & { code?: number };
1414

@@ -64,11 +64,4 @@ export const ReloadPageErrorFallback: FC<Pick<FallbackProps, "error">> = ({ erro
6464
);
6565
};
6666

67-
export const handleError: ErrorBoundaryProps["onError"] = async (error, info) => {
68-
const url = window.location.toString();
69-
try {
70-
await getGitpodService().server.reportErrorBoundary(url, error.message || "Unknown Error");
71-
} catch (e) {
72-
console.error(e);
73-
}
74-
};
67+
export const handleError: ErrorBoundaryProps["onError"] = (error, info) => reportError("Error boundary", error, info);

components/dashboard/src/service/metrics.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ console.error = function (...args) {
4040
reportError(...args);
4141
};
4242

43-
function reportError(...args: any[]) {
43+
let commonDetails = {};
44+
export function updateCommonErrorDetails(update: { [key: string]: string | undefined }) {
45+
Object.assign(commonDetails, update);
46+
}
47+
48+
export function reportError(...args: any[]) {
4449
let err = undefined;
4550
let details = undefined;
4651
if (args[0] instanceof Error) {
@@ -61,22 +66,26 @@ function reportError(...args: any[]) {
6166
}
6267
}
6368

64-
let data = undefined;
69+
let data = {};
6570
if (details && typeof details === "object") {
66-
data = Object.fromEntries(
67-
Object.entries(details)
68-
.filter(([key, value]) => {
69-
return (
70-
typeof value === "string" ||
71-
typeof value === "number" ||
72-
typeof value === "boolean" ||
73-
value === null ||
74-
typeof value === "undefined"
75-
);
76-
})
77-
.map(([key, value]) => [key, String(value)]),
71+
data = Object.assign(
72+
data,
73+
Object.fromEntries(
74+
Object.entries(details)
75+
.filter(([key, value]) => {
76+
return (
77+
typeof value === "string" ||
78+
typeof value === "number" ||
79+
typeof value === "boolean" ||
80+
value === null ||
81+
typeof value === "undefined"
82+
);
83+
})
84+
.map(([key, value]) => [key, String(value)]),
85+
),
7886
);
7987
}
88+
data = Object.assign(data, commonDetails);
8089

8190
if (err) {
8291
metricsReporter.reportError(err, data);

components/dashboard/src/user-context.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import { User } from "@gitpod/gitpod-protocol";
88
import { useQueryClient } from "@tanstack/react-query";
99
import React, { createContext, useState, useContext, useMemo, useCallback } from "react";
10+
import { updateCommonErrorDetails } from "./service/metrics";
1011

1112
const UserContext = createContext<{
1213
user?: User;
@@ -18,10 +19,16 @@ const UserContext = createContext<{
1819
const UserContextProvider: React.FC = ({ children }) => {
1920
const [user, setUser] = useState<User>();
2021

22+
const updateErrorUserDetails = (user?: User) => {
23+
updateCommonErrorDetails({ userId: user?.id });
24+
};
25+
updateErrorUserDetails(user);
26+
2127
const client = useQueryClient();
2228

2329
const doSetUser = useCallback(
2430
(updatedUser: User) => {
31+
updateErrorUserDetails(updatedUser);
2532
if (user?.id !== updatedUser.id) {
2633
client.clear();
2734
}

components/public-api/typescript/src/metrics.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ export class MetricsReporter {
373373
properties["error_name"] = error.name;
374374
properties["error_message"] = error.message;
375375

376+
const workspaceId = properties["workspaceId"];
377+
const instanceId = properties["instanceId"];
378+
const userId = properties["userId"];
379+
376380
delete properties["workspaceId"];
377381
delete properties["instanceId"];
378382
delete properties["userId"];
@@ -381,9 +385,9 @@ export class MetricsReporter {
381385
component: this.options.clientName,
382386
errorStack: error.stack ?? String(error),
383387
version: this.options.clientVersion,
384-
workspaceId: properties["workspaceId"] ?? "",
385-
instanceId: properties["instanceId"] ?? "",
386-
userId: properties["userId"] ?? "",
388+
workspaceId: workspaceId ?? "",
389+
instanceId: instanceId ?? "",
390+
userId: userId ?? "",
387391
properties,
388392
});
389393
}

components/server/src/prometheus-metrics.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export function registerServerMetrics(registry: prometheusClient.Registry) {
2222
registry.registerMetric(imageBuildsStartedTotal);
2323
registry.registerMetric(imageBuildsCompletedTotal);
2424
registry.registerMetric(spicedbClientLatency);
25-
registry.registerMetric(dashboardErrorBoundary);
2625
registry.registerMetric(jwtCookieIssued);
2726
registry.registerMetric(jobStartedTotal);
2827
registry.registerMetric(jobsCompletedTotal);
@@ -264,15 +263,6 @@ export function observeSpicedbClientLatency(operation: string, outcome: Error |
264263
);
265264
}
266265

267-
export const dashboardErrorBoundary = new prometheusClient.Counter({
268-
name: "gitpod_dashboard_error_boundary_total",
269-
help: "Total number of errors caught by an error boundary in the dashboard",
270-
});
271-
272-
export function increaseDashboardErrorBoundaryCounter() {
273-
dashboardErrorBoundary.inc();
274-
}
275-
276266
export const jobStartedTotal = new prometheusClient.Counter({
277267
name: "gitpod_server_jobs_started_total",
278268
help: "Total number of errors caught by an error boundary in the dashboard",

components/server/src/workspace/gitpod-server-impl.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution";
144144
import { CostCenterJSON } from "@gitpod/gitpod-protocol/lib/usage";
145145
import { createCookielessId, maskIp } from "../analytics";
146146
import { getExperimentsClientForBackend } from "@gitpod/gitpod-protocol/lib/experiments/configcat-server";
147-
import { increaseDashboardErrorBoundaryCounter } from "../prometheus-metrics";
148147
import { LinkedInService } from "../linkedin-service";
149148
import { SnapshotService, WaitForSnapshotOptions } from "./snapshot-service";
150149
import { IncrementalPrebuildsService } from "../prebuilds/incremental-prebuilds-service";
@@ -3464,14 +3463,12 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
34643463
//
34653464
//#endregion
34663465

3466+
/**
3467+
* TODO(ak)
3468+
* @deprecated remove it after dashboard is deployed. It was replaced with error reporting in GCP.
3469+
*/
34673470
async reportErrorBoundary(ctx: TraceContextWithSpan, url: string, message: string): Promise<void> {
3468-
// Cap message and url length so the entries aren't of unbounded length
3469-
log.warn("dashboard error boundary", {
3470-
message: (message || "").substring(0, 200),
3471-
url: (url || "").substring(0, 200),
3472-
userId: this.userID,
3473-
});
3474-
increaseDashboardErrorBoundaryCounter();
3471+
// no-op
34753472
}
34763473

34773474
async getIDToken(): Promise<void> {}

0 commit comments

Comments
 (0)