mirror of
https://github.com/uetchy/namae.git
synced 2025-03-17 04:30:31 +09:00
feat: add sentry
This commit is contained in:
parent
85520b2417
commit
a7efe886ab
@ -1,9 +1,5 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"name": "Root",
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"name": "API",
|
||||
"path": "api"
|
||||
|
@ -5,11 +5,12 @@
|
||||
"build": "NODE_ENV=production react-scripts build",
|
||||
"eject": "react-scripts eject",
|
||||
"now-build": "yarn build",
|
||||
"now-dev": "BROWSER=none react-scripts start",
|
||||
"start": "react-scripts start",
|
||||
"now-dev": "NODE_ENV=development BROWSER=none react-scripts start",
|
||||
"start": "NODE_ENV=development react-scripts start",
|
||||
"test": "react-scripts test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/browser": "^5.6.3",
|
||||
"fetch-suspense": "^1.2.0",
|
||||
"i18next": ">=17.0.12",
|
||||
"i18next-browser-languagedetector": "^3.0.3",
|
||||
@ -33,7 +34,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/jest-dom": "^4.1.0",
|
||||
"@testing-library/react": "^9.1.3",
|
||||
"@testing-library/react": "^9.1.4",
|
||||
"@types/i18next-node-fs-backend": "^2.1.0",
|
||||
"@types/jest": "^24.0.18",
|
||||
"@types/node": "^12.7.3",
|
||||
|
@ -1,7 +1,8 @@
|
||||
import React, {useState} from 'react';
|
||||
import React, {useState, useEffect} from 'react';
|
||||
import styled, {createGlobalStyle} from 'styled-components';
|
||||
import {Helmet} from 'react-helmet';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {initGA, sendQueryStatistics} from './util/analytics';
|
||||
|
||||
import Welcome from './components/Welcome';
|
||||
import Form from './components/Form';
|
||||
@ -15,8 +16,13 @@ export default function App() {
|
||||
const [query, setQuery] = useState('');
|
||||
const {t} = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
initGA();
|
||||
}, []);
|
||||
|
||||
function onQuery(query: string) {
|
||||
setQuery(query);
|
||||
sendQueryStatistics(query.length);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -6,6 +6,7 @@ import 'react-tippy/dist/tippy.css';
|
||||
import BarLoader from 'react-spinners/BarLoader';
|
||||
import {GoInfo} from 'react-icons/go';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {sendError} from '../../util/analytics';
|
||||
|
||||
import {mobile} from '../../util/css';
|
||||
import {ExternalLink} from '../Links';
|
||||
@ -21,16 +22,7 @@ export const Card: React.FC<{title: string}> = ({title, children}) => {
|
||||
<CardContainer>
|
||||
<CardTitle>{title}</CardTitle>
|
||||
<CardContent>
|
||||
<ErrorBoundary>
|
||||
<Suspense
|
||||
fallback={
|
||||
<ResultContainer>
|
||||
<BarLoader />
|
||||
</ResultContainer>
|
||||
}>
|
||||
{children}
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
<ErrorHandler>{children}</ErrorHandler>
|
||||
</CardContent>
|
||||
</CardContainer>
|
||||
);
|
||||
@ -55,12 +47,12 @@ export const Repeater: React.FC<{
|
||||
return (
|
||||
<>
|
||||
{items.map((name) => (
|
||||
<CellError key={name}>{children(name)}</CellError>
|
||||
<ErrorHandler key={name}>{children(name)}</ErrorHandler>
|
||||
))}
|
||||
|
||||
{revealAlternatives
|
||||
? moreItems.map((name) => (
|
||||
<CellError key={name}>{children(name)}</CellError>
|
||||
<ErrorHandler key={name}>{children(name)}</ErrorHandler>
|
||||
))
|
||||
: null}
|
||||
{moreItems.length > 0 && !revealAlternatives ? (
|
||||
@ -208,24 +200,37 @@ export const Result: React.FC<{
|
||||
);
|
||||
};
|
||||
|
||||
// 1. getDerivedStateFromError
|
||||
// 2. render()
|
||||
// 3. componentDidCatch() send errorInfo to Sentry
|
||||
// 4. render(), now with eventId provided from Sentry
|
||||
class ErrorBoundary extends React.Component<
|
||||
{},
|
||||
{hasError: boolean; message: string}
|
||||
{hasError: boolean; message: string; eventId?: string}
|
||||
> {
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
this.state = {hasError: false, message: ''};
|
||||
this.state = {hasError: false, message: '', eventId: undefined};
|
||||
}
|
||||
|
||||
// used in SSR
|
||||
static getDerivedStateFromError(error: Error) {
|
||||
return {hasError: true, message: error.message};
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: any) {
|
||||
sendError(error, errorInfo).then((eventId) => {
|
||||
this.setState({eventId});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<Tooltip
|
||||
title={this.state.message}
|
||||
title={`${this.state.message}${
|
||||
this.state.eventId ? ` (${this.state.eventId})` : ''
|
||||
}`}
|
||||
position="bottom"
|
||||
arrow={true}
|
||||
animation="shift"
|
||||
@ -245,7 +250,7 @@ class ErrorBoundary extends React.Component<
|
||||
}
|
||||
}
|
||||
|
||||
const CellError: React.FC = ({children}) => (
|
||||
const ErrorHandler: React.FC = ({children}) => (
|
||||
<ErrorBoundary>
|
||||
<Suspense
|
||||
fallback={
|
||||
|
@ -3,22 +3,16 @@ import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
import {FullScreenSuspense} from './util/suspense';
|
||||
import {initSentry} from './util/analytics';
|
||||
import './util/i18n';
|
||||
|
||||
const Container = () => (
|
||||
initSentry();
|
||||
|
||||
ReactDOM.render(
|
||||
<FullScreenSuspense>
|
||||
<App />
|
||||
</FullScreenSuspense>
|
||||
</FullScreenSuspense>,
|
||||
document.getElementById('root'),
|
||||
);
|
||||
|
||||
ReactDOM.render(<Container />, document.getElementById('root'));
|
||||
|
||||
// register Google Analytics
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
import('react-ga').then((ReactGA) => {
|
||||
ReactGA.initialize('UA-28919359-15');
|
||||
ReactGA.pageview(window.location.pathname + window.location.search);
|
||||
});
|
||||
}
|
||||
|
||||
serviceWorker.register({});
|
||||
|
41
web/src/util/analytics.ts
Normal file
41
web/src/util/analytics.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import ReactGA from 'react-ga';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
|
||||
const isProduction = process.env.NODE_ENV !== 'development';
|
||||
|
||||
export function initGA() {
|
||||
if (isProduction) {
|
||||
ReactGA.initialize('UA-28919359-15');
|
||||
ReactGA.pageview(window.location.pathname + window.location.search);
|
||||
}
|
||||
}
|
||||
|
||||
export function sendQueryStatistics(queryLength: number) {
|
||||
if (isProduction) {
|
||||
ReactGA.event({
|
||||
category: 'Search',
|
||||
action: 'New search invoked',
|
||||
value: queryLength,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function initSentry() {
|
||||
if (isProduction) {
|
||||
Sentry.init({
|
||||
dsn: 'https://7ab2df74aead499b950ebef190cc40b7@sentry.io/1759299',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function sendError(error: Error, errorInfo: any): Promise<string> {
|
||||
return new Promise((resolve) => {
|
||||
if (isProduction) {
|
||||
Sentry.withScope((scope) => {
|
||||
scope.setExtras(errorInfo);
|
||||
const eventId = Sentry.captureException(error);
|
||||
resolve(eventId);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
@ -1091,6 +1091,58 @@
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
|
||||
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
|
||||
|
||||
"@sentry/browser@^5.6.3":
|
||||
version "5.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.6.3.tgz#5cc37b0443eba55ad13c13d34d6b95ff30dfbfe3"
|
||||
integrity sha512-bP1LTbcKPOkkmfJOAM6c7WZ0Ov0ZEW6B9keVZ9wH9fw/lBPd9UyDMDCwJ+FAYKz9M9S5pxQeJ4Ebd7WUUrGVAQ==
|
||||
dependencies:
|
||||
"@sentry/core" "5.6.2"
|
||||
"@sentry/types" "5.6.1"
|
||||
"@sentry/utils" "5.6.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/core@5.6.2":
|
||||
version "5.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.6.2.tgz#8c5477654a83ebe41a72e86a79215deb5025e418"
|
||||
integrity sha512-grbjvNmyxP5WSPR6UobN2q+Nss7Hvz+BClBT8QTr7VTEG5q89TwNddn6Ej3bGkaUVbct/GpVlI3XflWYDsnU6Q==
|
||||
dependencies:
|
||||
"@sentry/hub" "5.6.1"
|
||||
"@sentry/minimal" "5.6.1"
|
||||
"@sentry/types" "5.6.1"
|
||||
"@sentry/utils" "5.6.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/hub@5.6.1":
|
||||
version "5.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.6.1.tgz#9f355c0abcc92327fbd10b9b939608aa4967bece"
|
||||
integrity sha512-m+OhkIV5yTAL3R1+XfCwzUQka0UF/xG4py8sEfPXyYIcoOJ2ZTX+1kQJLy8QQJ4RzOBwZA+DzRKP0cgzPJ3+oQ==
|
||||
dependencies:
|
||||
"@sentry/types" "5.6.1"
|
||||
"@sentry/utils" "5.6.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/minimal@5.6.1":
|
||||
version "5.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.6.1.tgz#09d92b26de0b24555cd50c3c33ba4c3e566009a1"
|
||||
integrity sha512-ercCKuBWHog6aS6SsJRuKhJwNdJ2oRQVWT2UAx1zqvsbHT9mSa8ZRjdPHYOtqY3DoXKk/pLUFW/fkmAnpdMqRw==
|
||||
dependencies:
|
||||
"@sentry/hub" "5.6.1"
|
||||
"@sentry/types" "5.6.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/types@5.6.1":
|
||||
version "5.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.6.1.tgz#5915e1ee4b7a678da3ac260c356b1cb91139a299"
|
||||
integrity sha512-Kub8TETefHpdhvtnDj3kKfhCj0u/xn3Zi2zIC7PB11NJHvvPXENx97tciz4roJGp7cLRCJsFqCg4tHXniqDSnQ==
|
||||
|
||||
"@sentry/utils@5.6.1":
|
||||
version "5.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.6.1.tgz#69d9e151e50415bc91f2428e3bcca8beb9bc2815"
|
||||
integrity sha512-rfgha+UsHW816GqlSRPlniKqAZylOmQWML2JsujoUP03nPu80zdN43DK9Poy/d9OxBxv0gd5K2n+bFdM2kqLQQ==
|
||||
dependencies:
|
||||
"@sentry/types" "5.6.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sheerun/mutationobserver-shim@^0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b"
|
||||
@ -1199,10 +1251,10 @@
|
||||
"@svgr/plugin-svgo" "^4.3.1"
|
||||
loader-utils "^1.2.3"
|
||||
|
||||
"@testing-library/dom@^6.0.0":
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-6.1.0.tgz#8d5a954158e81ecd7c994907f4ec240296ed823b"
|
||||
integrity sha512-qivqFvnbVIH3DyArFofEU/jlOhkGIioIemOy9A9M/NQTpPyDDQmtVkAfoB18RKN581f0s/RJMRBbq9WfMIhFTw==
|
||||
"@testing-library/dom@^6.1.0":
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-6.4.0.tgz#aaf7fceba1272516fc7c5ac0716a24f63ea6cdaa"
|
||||
integrity sha512-uQFwl+mIH9THk9Q9qVZKBgoL/6ahVEQu9bDeOmY5yB8uc62L2Z9eYs0g7zNTdMsg4I0bOdPPMs/sNETYP5+PEw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
"@sheerun/mutationobserver-shim" "^0.3.2"
|
||||
@ -1226,13 +1278,13 @@
|
||||
pretty-format "^24.0.0"
|
||||
redent "^3.0.0"
|
||||
|
||||
"@testing-library/react@^9.1.3":
|
||||
version "9.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-9.1.3.tgz#3fb495227322ea36cd817532441dabb552e0d6ce"
|
||||
integrity sha512-qFVo6TsEbpEFpOmKjIxMHDujOKVdvVpcYFcUfJeWBqMO8eja5pN9SZnt6W6AzW3a1MRvRfw3X0Fhx3eXnBJxjA==
|
||||
"@testing-library/react@^9.1.4":
|
||||
version "9.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-9.1.4.tgz#4cc1a228a944c0f468ee501e7da1651d8bbd9902"
|
||||
integrity sha512-fQ/PXZoLcmnS1W5ZiM3P7XBy2x6Hm9cJAT/ZDuZKzJ1fS1rN3j31p7ReAqUe3N1kJ46sNot0n1oiGbz7FPU+FA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
"@testing-library/dom" "^6.0.0"
|
||||
"@testing-library/dom" "^6.1.0"
|
||||
"@types/testing-library__react" "^9.1.0"
|
||||
|
||||
"@types/babel__core@^7.1.0":
|
||||
@ -9829,7 +9881,7 @@ ts-pnp@^1.1.2:
|
||||
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.4.tgz#ae27126960ebaefb874c6d7fa4729729ab200d90"
|
||||
integrity sha512-1J/vefLC+BWSo+qe8OnJQfWTYRS6ingxjwqmHMqaMxXMj7kFtKLgAaYW3JeX3mktjgUL+etlU8/B4VUAUI9QGw==
|
||||
|
||||
tslib@^1.8.1, tslib@^1.9.0:
|
||||
tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
|
||||
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
|
||||
|
Loading…
x
Reference in New Issue
Block a user