From 8d69708bc87a67213c0c1cd17f3ebdd72399e354 Mon Sep 17 00:00:00 2001 From: Frederic Henrichs Date: Thu, 12 Dec 2024 09:30:25 +0100 Subject: [PATCH] frontend: create a error file containing a backtrace and download it when an unhandled exception is thrown in the app. --- frontend/src/components/Frame.tsx | 16 +++++++++------- frontend/src/index.tsx | 15 +++++++++++++++ frontend/src/worker.ts | 18 ++++++++++++------ 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/Frame.tsx b/frontend/src/components/Frame.tsx index a0e18c5..03ac099 100644 --- a/frontend/src/components/Frame.tsx +++ b/frontend/src/components/Frame.tsx @@ -5,7 +5,7 @@ import Worker from '../worker?worker' import { Row, Spinner } from 'react-bootstrap'; import { connected, connected_to, secret } from './charger_list'; import { setAppNavigation } from './Navbar'; -import { enableLogging, refreshPromise } from '../utils'; +import { enableLogging, refresh_access_token } from '../utils'; import Median from "median-js-bridge"; import i18n from '../i18n'; import { showAlert } from './Alert'; @@ -89,12 +89,6 @@ export class Frame extends Component { handleErrorMessage(msg: Message) { connected.value = false; connected_to.value = ""; - if (msg.data.translation) { - const error = msg.data as ErrorMessage; - showAlert(i18n.t(error.translation, error.format) as string, "danger"); - } else { - showAlert(msg.data, "danger"); - } } startWorker() { @@ -110,6 +104,14 @@ export class Frame extends Component { this.worker.terminate(); break; } + } else if (e.data.unresolved) { + const msg = JSON.stringify(e.data.msg); + const blob = new Blob([msg]); + const url = URL.createObjectURL(blob); + const filename = `mystaging_error_${Date.now()}.json`; + if (Median.isNativeApp()) { + Median.share.downloadFile({url: url, filename: filename, open: true}); + } } else { const msg = e.data as Message; switch (msg.type) { diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 5254991..aa8ed84 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -46,6 +46,21 @@ setInterval(async () => { await refresh_access_token(); }, 1000 * 60 * 5); +addEventListener("unhandledrejection", (event) => { + const stack = event.reason.stack.split("\n"); + + const evt = { + message: event.reason.message, + stack: stack + } + const msg = JSON.stringify(evt); + const blob = new Blob([msg]); + const url = URL.createObjectURL(blob); + const filename = `mystaging_error_${Date.now()}.json` + if (Median.isNativeApp()) { + Median.share.downloadFile({url: url, filename: filename, open: true}); + } +}); export function App() { const {t} = useTranslation("", {useSuspense: false}); diff --git a/frontend/src/worker.ts b/frontend/src/worker.ts index 6b76461..7fe5996 100644 --- a/frontend/src/worker.ts +++ b/frontend/src/worker.ts @@ -27,6 +27,16 @@ const tunnel_url = import.meta.env.VITE_BACKEND_WS_URL + "/ws?key_id=" let wgClient: Client | undefined = undefined; let setup_data: SetupMessage; +self.addEventListener("unhandledrejection", (event) => { + const stack = event.reason.stack.split("\n"); + + const evt = { + message: event.reason.message, + stack: stack + } + self.postMessage({unresolved: true, msg: evt}); +}); + self.addEventListener("message", async (e: MessageEvent) => { if (typeof e.data === "string") { switch (e.data) { @@ -122,8 +132,9 @@ function disconnect_cb() { async function start_connection(setup_data: SetupMessage) { let keys: any; + const url = import.meta.env.VITE_BACKEND_URL + "/charger/get_key?cid=" + setup_data.chargerID; try { - const resp = await fetch(import.meta.env.VITE_BACKEND_URL + "/charger/get_key?cid=" + setup_data.chargerID, {credentials: "same-origin"}); + const resp = await fetch(url, {credentials: "same-origin"}); if (resp.status === 404) { const msg: Message = { type: MessageType.Error, @@ -150,11 +161,6 @@ async function start_connection(setup_data: SetupMessage) { } keys = await resp.json(); } catch (e) { - const msg: Message = { - type: MessageType.Error, - data: `Getting connection key crashed: ${e}`, - } - self.postMessage(msg); return; } const decrypted_keys = decrypt_keys(keys, setup_data.secret);