mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-22 07:00:58 -05:00
feat: add global error handling and reporting
This commit is contained in:
parent
56126fa303
commit
de1b947b7d
5 changed files with 139 additions and 27 deletions
|
@ -146,6 +146,7 @@
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sass": "^1.35.1",
|
"sass": "^1.35.1",
|
||||||
"shade-blend-color": "^1.0.0",
|
"shade-blend-color": "^1.0.0",
|
||||||
|
"stacktrace-js": "^2.0.2",
|
||||||
"styled-components": "^5.3.0",
|
"styled-components": "^5.3.0",
|
||||||
"typescript": "^4.4.2",
|
"typescript": "^4.4.2",
|
||||||
"ulid": "^2.3.0",
|
"ulid": "^2.3.0",
|
||||||
|
|
63
src/lib/ErrorBoundary.tsx
Normal file
63
src/lib/ErrorBoundary.tsx
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import axios from "axios";
|
||||||
|
import * as stackTrace from "stacktrace-js";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { useEffect, useErrorBoundary } from "preact/hooks";
|
||||||
|
|
||||||
|
import { GIT_REVISION } from "../revision";
|
||||||
|
import { Children } from "../types/Preact";
|
||||||
|
|
||||||
|
const CrashContainer = styled.div`
|
||||||
|
height: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: Children;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ERROR_URL = "https://reporting.revolt.chat";
|
||||||
|
|
||||||
|
export default function ErrorBoundary({ children }: Props) {
|
||||||
|
const [error, ignoreError] = useErrorBoundary();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (error) {
|
||||||
|
stackTrace.fromError(error).then((stackframes) =>
|
||||||
|
axios.post(ERROR_URL, {
|
||||||
|
stackframes,
|
||||||
|
rawStackTrace: error.stack,
|
||||||
|
origin: window.origin,
|
||||||
|
commitSHA: GIT_REVISION,
|
||||||
|
userAgent: navigator.userAgent,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [error]);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<CrashContainer>
|
||||||
|
<h3>Client Crash Report</h3>
|
||||||
|
<button onClick={ignoreError}>
|
||||||
|
Ignore error and try to reload app
|
||||||
|
</button>
|
||||||
|
<button onClick={() => location.reload()}>Refresh page</button>
|
||||||
|
<pre>
|
||||||
|
<code>{error?.stack}</code>
|
||||||
|
</pre>
|
||||||
|
<div>This error has been automatically reported.</div>
|
||||||
|
</CrashContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>{children}</>;
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ import { Route, Switch } from "react-router-dom";
|
||||||
|
|
||||||
import { lazy, Suspense } from "preact/compat";
|
import { lazy, Suspense } from "preact/compat";
|
||||||
|
|
||||||
|
import ErrorBoundary from "../lib/ErrorBoundary";
|
||||||
|
|
||||||
import Context from "../context";
|
import Context from "../context";
|
||||||
import { CheckAuth } from "../context/revoltjs/CheckAuth";
|
import { CheckAuth } from "../context/revoltjs/CheckAuth";
|
||||||
|
|
||||||
|
@ -15,33 +17,35 @@ const RevoltApp = lazy(() => import("./RevoltApp"));
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
return (
|
return (
|
||||||
<Context>
|
<ErrorBoundary>
|
||||||
<Masks />
|
<Context>
|
||||||
{/*
|
<Masks />
|
||||||
// @ts-expect-error typings mis-match between preact... and preact? */}
|
{/*
|
||||||
<Suspense fallback={<Preloader type="spinner" />}>
|
// @ts-expect-error typings mis-match between preact... and preact? */}
|
||||||
<Switch>
|
<Suspense fallback={<Preloader type="spinner" />}>
|
||||||
<Route path="/login/verify/:token">
|
<Switch>
|
||||||
<Login />
|
<Route path="/login/verify/:token">
|
||||||
</Route>
|
|
||||||
<Route path="/login/reset/:token">
|
|
||||||
<Login />
|
|
||||||
</Route>
|
|
||||||
<Route path="/invite/:code">
|
|
||||||
<Invite />
|
|
||||||
</Route>
|
|
||||||
<Route path="/login">
|
|
||||||
<CheckAuth>
|
|
||||||
<Login />
|
<Login />
|
||||||
</CheckAuth>
|
</Route>
|
||||||
</Route>
|
<Route path="/login/reset/:token">
|
||||||
<Route path="/">
|
<Login />
|
||||||
<CheckAuth auth>
|
</Route>
|
||||||
<RevoltApp />
|
<Route path="/invite/:code">
|
||||||
</CheckAuth>
|
<Invite />
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
<Route path="/login">
|
||||||
</Suspense>
|
<CheckAuth>
|
||||||
</Context>
|
<Login />
|
||||||
|
</CheckAuth>
|
||||||
|
</Route>
|
||||||
|
<Route path="/">
|
||||||
|
<CheckAuth auth>
|
||||||
|
<RevoltApp />
|
||||||
|
</CheckAuth>
|
||||||
|
</Route>
|
||||||
|
</Switch>
|
||||||
|
</Suspense>
|
||||||
|
</Context>
|
||||||
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ export default function Developer() {
|
||||||
const client = useContext(AppContext);
|
const client = useContext(AppContext);
|
||||||
const userPermission = client.user!.permission;
|
const userPermission = client.user!.permission;
|
||||||
const [ping, setPing] = useState<undefined | number>(client.websocket.ping);
|
const [ping, setPing] = useState<undefined | number>(client.websocket.ping);
|
||||||
|
const [crash, setCrash] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setInterval(
|
const timer = setInterval(
|
||||||
|
@ -44,6 +45,8 @@ export default function Developer() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ padding: "16px" }}>
|
<div style={{ padding: "16px" }}>
|
||||||
|
<a onClick={() => setCrash(true)}>click to crash app</a>
|
||||||
|
{crash && (window as any).sus.sus()}
|
||||||
{/*<span>
|
{/*<span>
|
||||||
<b>Voice Status:</b> {VoiceStatus[voice.status]}
|
<b>Voice Status:</b> {VoiceStatus[voice.status]}
|
||||||
</span>
|
</span>
|
||||||
|
|
41
yarn.lock
41
yarn.lock
|
@ -2106,6 +2106,13 @@ entities@~2.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
|
||||||
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
|
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
|
||||||
|
|
||||||
|
error-stack-parser@^2.0.6:
|
||||||
|
version "2.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8"
|
||||||
|
integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==
|
||||||
|
dependencies:
|
||||||
|
stackframe "^1.1.1"
|
||||||
|
|
||||||
es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2:
|
es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2:
|
||||||
version "1.18.5"
|
version "1.18.5"
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.5.tgz#9b10de7d4c206a3581fd5b2124233e04db49ae19"
|
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.5.tgz#9b10de7d4c206a3581fd5b2124233e04db49ae19"
|
||||||
|
@ -3962,6 +3969,11 @@ source-map-url@^0.4.0:
|
||||||
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
|
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
|
||||||
integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
|
integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
|
||||||
|
|
||||||
|
source-map@0.5.6:
|
||||||
|
version "0.5.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
|
||||||
|
integrity sha1-dc449SvwczxafwwRjYEzSiu19BI=
|
||||||
|
|
||||||
source-map@^0.5.0:
|
source-map@^0.5.0:
|
||||||
version "0.5.7"
|
version "0.5.7"
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||||
|
@ -3994,6 +4006,35 @@ sprintf-js@~1.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||||
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
||||||
|
|
||||||
|
stack-generator@^2.0.5:
|
||||||
|
version "2.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.5.tgz#fb00e5b4ee97de603e0773ea78ce944d81596c36"
|
||||||
|
integrity sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q==
|
||||||
|
dependencies:
|
||||||
|
stackframe "^1.1.1"
|
||||||
|
|
||||||
|
stackframe@^1.1.1:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303"
|
||||||
|
integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==
|
||||||
|
|
||||||
|
stacktrace-gps@^3.0.4:
|
||||||
|
version "3.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz#7688dc2fc09ffb3a13165ebe0dbcaf41bcf0c69a"
|
||||||
|
integrity sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg==
|
||||||
|
dependencies:
|
||||||
|
source-map "0.5.6"
|
||||||
|
stackframe "^1.1.1"
|
||||||
|
|
||||||
|
stacktrace-js@^2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b"
|
||||||
|
integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==
|
||||||
|
dependencies:
|
||||||
|
error-stack-parser "^2.0.6"
|
||||||
|
stack-generator "^2.0.5"
|
||||||
|
stacktrace-gps "^3.0.4"
|
||||||
|
|
||||||
string-width@^4.2.0:
|
string-width@^4.2.0:
|
||||||
version "4.2.2"
|
version "4.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"
|
||||||
|
|
Loading…
Reference in a new issue