1. release
typeof Sentry === 'object' && Sentry.init({
...
release: `c2m-simulation-front@${__RELEASE}`,
...
});
2. environment
typeof Sentry === 'object' && Sentry.init({
...
environment: process.env.NODE_ENV,
...
});
3. user feedback
1. fallback参数为react组件
// app.js
import React from "react";
import ReactDOM from 'react-dom';
import * as Sentry from "@sentry/react";
import ErrorTips from './ErrorTips';
ReactDOM.render(<Sentry.ErrorBoundary fallback={<ErrorTips />} showDialog>
<ConfigProvider locale={zhCN}>
<Provider store={rootStore}>
<MyShopPageframe appRoutes={routes} />
</Provider>
</ConfigProvider></Sentry.ErrorBoundary>, document.getElementById('app'));
// ErrorTips.tsx
import React from 'react';
import styled from 'styled-components';
import errorImage from './src/web/images/error-page-bg.png';
const ErrorWrap = styled.div`
width: 300px;
height: 300px;
margin: 200px auto;
background: url(${errorImage});
text-align: center;
color: rgba(0, 0, 0, .45);
`;
const ErrorTips = (): React.ReactElement => {
return <ErrorWrap>
<p>页面发生了错误,期待您的反馈~</p>
</ErrorWrap>;
}
export default ErrorTips;
2. fallback参数为一个函数
// app.js
ReactDOM.render(<Sentry.ErrorBoundary fallback={({ error, componentStack, resetError }) => (
<React.Fragment>
<div>页面发生了错误,具体信息如下:</div>
<div>{error.toString()}</div>
<div>{componentStack}</div>
<button
onClick={() => {
resetError();
}}
>
点击提交报错信息
</button>
</React.Fragment>
)} showDialog>
<ConfigProvider locale={zhCN}>
<Provider store={rootStore}>
<MyShopPageframe appRoutes={routes} />
</Provider>
</ConfigProvider>
</Sentry.ErrorBoundary>, document.getElementById('app'));
3. 使用多个错误边界
import React from 'react';
import * as Sentry from '@sentry/react';
function App({ props }) {
return (
<React.Fragment>
<Sentry.ErrorBoundary
beforeCapture={(scope) => {
scope.setTag("location", "first");
scope.setTag("anotherTag", "anotherValue");
}}
>
<Route to="path/to/first" component={First} />
</Sentry.ErrorBoundary>
<Sentry.ErrorBoundary
beforeCapture={(scope) => {
scope.setTag("location", "second");
}}
>
<Route to="path/to/second" component={Second} />
</Sentry.ErrorBoundary>
</React.Fragment>
);
}
export default App;
4. source maps
1. 有无source maps的报错信息区别
1.1 无source maps
1.2 有source maps
2. 推荐使用webpack插件
2.1 安装
npm install --save-dev @sentry/webpack-plugin
// or
yarn add --dev @sentry/webpack-plugin
2.2 配置
运行下方命令
export SENTRY_URL=https://sentry-api.jd.com/
提示输入token(token的配置在Settings > Account > API > Auth Tokens路径下),输入后配置完成
2.3 webpack配置
...
plugins: [
...
new SentryWebpackPlugin({
// sentry-cli configuration - can also be done directly through sentry-cli
// see https://docs.sentry.io/product/cli/configuration/ for details
// vcsRemote: 'sentry-api.jd.com',
// token: process.env.SENTRY_AUTH_TOKEN,
org: "yot",
project: "c2m-simulation-front",
release: `c2m-simulation-front@${_dateStr}`,
// other SentryWebpackPlugin configuration
include: ".",
ignore: ["node_modules", "config/*.js"],
}),
]
...
sdk 指纹:自定义粒度的报错
typeof Sentry === 'object' && Sentry.init({
...
beforeSend(event, hint) {
const error = hint.originalException;
if (error && error.message) {
if (error instanceof ReferenceError) {
event.fingerprint = ['reference-error-xx-is-not-defined'];
}
if (error.message.match(/repeated request/i)) {
event.fingerprint = ['repeated-request'];
}
}
return event;
},
});
5. 面包屑
默认支持用户路径的输出
typeof Sentry === 'object' && Sentry.init({
...
integrations: [
// new Integrations.BrowserTracing(),
new Sentry.Integrations.Breadcrumbs({
console: false,
}),
],
...
});
// 配置项支持以下参数
{
// 记录对 `console.log`、`console.debug` 等的调用
console: boolean;
// 记录所有点击和按键事件
// - 当提供带有 `serializeAttribute` key 的对象时,
// 面包屑集成将在 DOM 元素中查找给定的属性,同时生成面包屑路径。
// 匹配的元素后跟它们的自定义属性,而不是它们的 `id` 或 `class` 名称。
dom: boolean | { serializeAttribute: string | string[] };
// 记录使用 `Fetch API` 完成的 `HTTP` 请求
fetch: boolean;
// 记录对 `history.pushState` 的调用
history: boolean;
// 每当我们向服务器发送事件时记录
sentry: boolean;
// 记录使用 XHR API 完成的 HTTP 请求
xhr: boolean;
}
过滤报错
配置路径
[Project] > Project Settings > Inbound Filters.
其他
- 推荐一款chrome插件:Ajax Intercepter 修改ajax接口响应