diff options
| author | Haishan <[email protected]> | 2018-12-23 21:42:42 +0800 |
|---|---|---|
| committer | Haishan <[email protected]> | 2018-12-23 21:42:42 +0800 |
| commit | a72115067a8aee5dce75ad34a280a2588ac24c0e (patch) | |
| tree | e9a2d91a48b5e4c8d1de7a7ce8fd1c65dde760fb /src/components | |
| parent | eb564f06fe353438889ab2bb557c715529190128 (diff) | |
feat: integrate sentry
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/ErrorBoundary.js | 53 | ||||
| -rw-r--r-- | src/components/Root.js | 31 |
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} /> |
