|
| 1 | +/** |
| 2 | + * Copyright (c) 2023 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 { GitpodHostUrl } from "@gitpod/gitpod-protocol/lib/util/gitpod-host-url"; |
| 8 | +import { MetricsReporter } from "@gitpod/public-api/lib/metrics"; |
| 9 | +import { getExperimentsClient } from "../experiments/client"; |
| 10 | + |
| 11 | +const originalConsoleError = console.error; |
| 12 | + |
| 13 | +const options = { |
| 14 | + gitpodUrl: new GitpodHostUrl(window.location.href).withoutWorkspacePrefix().toString(), |
| 15 | + clientName: "dashboard", |
| 16 | + clientVersion: "", |
| 17 | + logError: originalConsoleError.bind(console), |
| 18 | + isEnabled: () => getExperimentsClient().getValueAsync("dashboard_metrics_enabled", false, {}), |
| 19 | +}; |
| 20 | +fetch("/api/version").then(async (res) => { |
| 21 | + const version = await res.text(); |
| 22 | + options.clientVersion = version; |
| 23 | +}); |
| 24 | +const metricsReporter = new MetricsReporter(options); |
| 25 | +metricsReporter.startReporting(); |
| 26 | + |
| 27 | +window.addEventListener("unhandledrejection", (event) => { |
| 28 | + reportError("Unhandled promise rejection", event.reason); |
| 29 | +}); |
| 30 | +window.addEventListener("error", (event) => { |
| 31 | + let message = "Unhandled error"; |
| 32 | + if (event.message) { |
| 33 | + message += ": " + event.message; |
| 34 | + } |
| 35 | + reportError(message, event.error); |
| 36 | +}); |
| 37 | + |
| 38 | +console.error = function (...args) { |
| 39 | + originalConsoleError.apply(console, args); |
| 40 | + reportError(...args); |
| 41 | +}; |
| 42 | + |
| 43 | +function reportError(...args: any[]) { |
| 44 | + let err = undefined; |
| 45 | + let details = undefined; |
| 46 | + if (args[0] instanceof Error) { |
| 47 | + err = args[0]; |
| 48 | + details = args[1]; |
| 49 | + } else if (typeof args[0] === "string") { |
| 50 | + err = new Error(args[0]); |
| 51 | + if (args[1] instanceof Error) { |
| 52 | + err.message += ": " + args[1].message; |
| 53 | + err.name = args[1].name; |
| 54 | + err.stack = args[1].stack; |
| 55 | + details = args[2]; |
| 56 | + } else if (typeof args[1] === "string") { |
| 57 | + err.message += ": " + args[1]; |
| 58 | + details = args[2]; |
| 59 | + } else { |
| 60 | + details = args[1]; |
| 61 | + } |
| 62 | + } |
| 63 | + |
| 64 | + let data = undefined; |
| 65 | + 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)]), |
| 78 | + ); |
| 79 | + } |
| 80 | + |
| 81 | + if (err) { |
| 82 | + metricsReporter.reportError(err, data); |
| 83 | + } |
| 84 | +} |
0 commit comments