summaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorHaishan <[email protected]>2018-12-23 21:42:42 +0800
committerHaishan <[email protected]>2018-12-23 21:42:42 +0800
commita72115067a8aee5dce75ad34a280a2588ac24c0e (patch)
treee9a2d91a48b5e4c8d1de7a7ce8fd1c65dde760fb /src/components
parenteb564f06fe353438889ab2bb557c715529190128 (diff)
feat: integrate sentry
Diffstat (limited to 'src/components')
-rw-r--r--src/components/ErrorBoundary.js53
-rw-r--r--src/components/Root.js31
2 files changed, 70 insertions, 14 deletions
diff --git a/src/components/ErrorBoundary.js b/src/components/ErrorBoundary.js
new file mode 100644
index 0000000..a44ca92
--- /dev/null
+++ b/src/components/ErrorBoundary.js
@@ -0,0 +1,53 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { getSentry } from '../misc/sentry';
+
+// XXX this is no Hook equivalents for componentDidCatch
+// we have to use class for now
+
+class ErrorBoundary extends Component {
+ static propTypes = {
+ children: PropTypes.node
+ };
+
+ state = { error: null };
+
+ loadSentry = async () => {
+ if (this.sentry) return this.sentry;
+ const x = await getSentry();
+ this.sentry = x;
+ return this.sentry;
+ };
+
+ componentDidMount() {
+ this.loadSentry();
+ }
+
+ componentDidCatch(error, errorInfo) {
+ this.setState({ error });
+ this.loadSentry().then(Sentry => {
+ Sentry.withScope(scope => {
+ Object.keys(errorInfo).forEach(key => {
+ scope.setExtra(key, errorInfo[key]);
+ });
+ Sentry.captureException(error);
+ });
+ });
+ }
+
+ showReportDialog = () => {
+ this.loadSentry().then(Sentry => Sentry.showReportDialog());
+ };
+
+ render() {
+ if (this.state.error) {
+ //render fallback UI
+ return <a onClick={this.showReportDialog}>Report feedback</a>;
+ } else {
+ //when there's not an error, render children untouched
+ return this.props.children;
+ }
+ }
+}
+
+export default ErrorBoundary;
diff --git a/src/components/Root.js b/src/components/Root.js
index a5f56e7..dc96e22 100644
--- a/src/components/Root.js
+++ b/src/components/Root.js
@@ -4,6 +4,7 @@ import { HashRouter as Router, Route } from 'react-router-dom';
// import { hot } from 'react-hot-loader';
// import createHistory from 'history/createHashHistory';
// import createHistory from 'history/createBrowserHistory';
+import ErrorBoundary from 'c/ErrorBoundary';
import SideBar from 'c/SideBar';
import Home from 'c/Home';
import Logs from 'c/Logs';
@@ -23,21 +24,23 @@ import s0 from './Root.module.scss';
window.store = store;
const Root = () => (
- <Provider store={store}>
- <Router>
- <div className={s0.app}>
- <APIDiscovery />
- <Route path="/" render={() => <SideBar />} />
- <div className={s0.content}>
- <Route exact path="/" render={() => <Home />} />
- <Route exact path="/overview" render={() => <Home />} />
- <Route exact path="/configs" render={() => <Config />} />
- <Route exact path="/logs" render={() => <Logs />} />
- <Route exact path="/proxies" render={() => <Proxies />} />
+ <ErrorBoundary>
+ <Provider store={store}>
+ <Router>
+ <div className={s0.app}>
+ <APIDiscovery />
+ <Route path="/" render={() => <SideBar />} />
+ <div className={s0.content}>
+ <Route exact path="/" render={() => <Home />} />
+ <Route exact path="/overview" render={() => <Home />} />
+ <Route exact path="/configs" render={() => <Config />} />
+ <Route exact path="/logs" render={() => <Logs />} />
+ <Route exact path="/proxies" render={() => <Proxies />} />
+ </div>
</div>
- </div>
- </Router>
- </Provider>
+ </Router>
+ </Provider>
+ </ErrorBoundary>
);
// <Route exact path="/__0" component={StyleGuide} />
// <Route exact path="/__1" component={Loading} />