内容源于:https://docs.sentry.io/platforms/javascript/guides/react/
系列
脑图
公众号:黑客下午茶
快速开始
Sentry
的React SDK
支持自动报告错误和异常。SDK
是@sentry/browser
的包装器,增加了与React
相关的功能。@sentry/browser
中可用的所有方法都可以从@sentry/react
中导入。
安装
Sentry
通过在应用程序 runtime
使用 SDK
捕获数据。
# 使用 npm
npm install --save @sentry/react @sentry/tracing
# 使用 yarn
yarn add @sentry/react @sentry/tracing
export const _frontmatter = {}
配置
配置应该在应用程序的生命周期中尽早进行。
import React from "react";
import ReactDOM from "react-dom";
import * as Sentry from "@sentry/react";
import { Integrations } from "@sentry/tracing";
import App from "./App";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
integrations: [new Integrations.BrowserTracing()],
// 我们建议在生产中调整此值,或使用 tracesSampler 进行更精细的控制
tracesSampleRate: 1.0,
});
ReactDOM.render(<App />, document.getElementById("root"));
// 也可以与 React Concurrent Mode 一起使用
// ReactDOM.createRoot(document.getElementById('root')).render(<App />);
一旦完成,所有未处理的异常都会被 Sentry
自动捕获。
添加 Error Boundary
如果您使用的是 React 16
或更高版本,则可以使用 Error Boundary
组件将组件树内部的 Javascript
错误自动发送到 Sentry
,并设置回退 UI
。
设置 React Router
React Router 集成
旨在与我们的跟踪包一起使用。请在下方配置
部分了解有关 React Router Integration
及其选项的更多信息。
应用 Redux
要将 Sentry
应用于 Redux
,请在下方配置
部分了解有关 Redux Integration
及其选项的更多信息。
验证
此代码段包含一个故意错误,因此您可以在设置后立即测试一切是否正常:
return <button onClick={methodDoesNotExist}>Break the world</button>;
组件
Sentry React SDK
公开自定义组件,以便与 React 框架进行一级集成。
React Error Boundary
React SDK
导出一个错误边界组件,该组件利用 React component API
自动捕获 JavaScript
错误并将其从 React
组件树内部发送到 Sentry
。
import React from "react";
import * as Sentry from "@sentry/react";
<Sentry.ErrorBoundary fallback={<p>An error has occurred</p>}>
<Example />
</Sentry.ErrorBoundary>;
Sentry Error Boundary
也可用作高阶组件。
import React from "react";
import * as Sentry from "@sentry/react";
Sentry.withErrorBoundary(Example, { fallback: <p>an error has occurred</p> });
Note:在
development
模式下,React
会重新抛出在错误边界内捕获的错误。 这将导致使用上述设置向Sentry
报告两次错误,但这不会发生在您的生产版本中。
在下面的示例中,当 <Example />
组件遇到错误时,<Sentry.ErrorBoundary>
组件会将有关该错误的数据和组件树发送到 Sentry
,打开用户反馈对话框,并呈现 fallback UI
。
import React from "react";
import * as Sentry from "@sentry/react";
import { Example } from "../example";
function FallbackComponent() {
return <div>An error has occurred</div>;
}
const myFallback = <FallbackComponent />;
// Alternatively:
// const myFallback = () => <FallbackComponent />;
class App extends React.Component {
render() {
return (
<Sentry.ErrorBoundary fallback={myFallback} showDialog>
<Example />
</Sentry.ErrorBoundary>
);
}
}
export default App;
选项
ErrorBoundary
组件公开了各种可以传入以进行额外配置的属性。 没有必需的选项,但我们强烈建议您设置 fallback
组件。
showDialog
(boolean)
- 当
Error Boundary
捕捉到错误时,是否应呈现Sentry User Feedback Widget
。
dialogOptions
(Object)
- 传递到
Sentry User Feedback Widget
的选项。在下方查看所有可能的自定义选项。
fallback
(React.ReactNode or Function)
- 当错误边界捕获错误时要呈现的
React
元素。可以是实际的React
元素(即<Fallback />
),也可以是返回React
元素的函数。如果您提供一个函数,Sentry
将使用附加信息和帮助程序调用它(参见下面的示例)。
onError
(Function)
- 当
Error Boundary
遇到错误时调用的函数。如果您想将错误传播到Redux
之类的状态管理库中,或者您想检查由于错误而可能发生的任何副作用,onError
非常有用。
onUnmount
(Function)
- 在
ErrorBoundary componentWillUnmount()
上调用的函数。
beforeCapture
(Function)
*(5.20.0
及以上版本可用)
- 在将错误发送到
Sentry
之前调用的函数,允许将额外的标签(tag
)或上下文(context
)添加到错误中。
示例
设置 Fallback 函数(渲染属性)
下面是一个示例,其中使用渲染属性方法的 fallback
属性用于在错误时显示 fallback UI
。使用组件通过渲染属性提供的 resetError() API
重置时,fallback UI
会返回到标准组件状态。
import React from "react";
import * as Sentry from "@sentry/react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
message: "This is my app",
};
}
render() {
return (
<Sentry.ErrorBoundary
fallback={({ error, componentStack, resetError }) => (
<React.Fragment>
<div>You have encountered an error</div>
<div>{error.toString()}</div>
<div>{componentStack}</div>
<button
onClick={() => {
this.setState({ message: "This is my app" });
{/* When resetError() is called it will remove the Fallback component */}
{/* and render the Sentry ErrorBoundary's children in their initial state */}
resetError();
}}
>
Click here to reset!
</button>
</React.Fragment>
)}
>
<div>{this.state.message}</div>
{/* on click, this button sets an Object as a message, not a string. */}
{/* which will cause an error to occur in the component tree */}
<button
onClick={() => this.setState({ message: { text: "Hello World" } })}
>
Click here to change message!
</button>
</Sentry.ErrorBoundary>
);
}
}
export default App;
使用多个错误边界
(5.20.0 及以上版本可用)
当使用多个错误边界时,我们建议使用 beforeCapture
设置标签/上下文(tags/context)
,以便您可以知道错误发生在哪个错误边界。 在下面的示例中,我们根据错误渲染的路径将标记(tag
)附加到错误(error
)。
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;
React Profiler
@sentry/react
导出一个 withProfiler
高阶组件,该组件将 React
相关的 span
附加到作用域上的当前活动事务(transaction
)。
在下面的示例中,withProfiler
高阶组件用于检测 App
组件。
import React from "react";
import * as Sentry from "@sentry/react";
class App extends React.Component {
render() {
return (
<FancyComponent>
<NestedComponent someProp={2} />
<AnotherComponent />
</FancyComponent>
);
}
}
export default Sentry.withProfiler(App);
React Profiler
目前使用三种不同类型的操作码(op-codes
)生成 span
:react.mount
、react.render
和 react.update
。
react.mount
- 表示被分析组件
mount
所需时间的跨度。
react.render
- 表示被分析组件在页面上的时间跨度。只有在事务发生时
mount
和unmount
被分析的组件时,才会生成这个跨度。
react.update
- 表示被分析组件更新时的跨度。只有当被分析组件已
mount
时才生成此span
。
在
React Strict Mode
下,某些组件方法将被调用两次。这可能会导致在事务中出现重复的react.mount
跨度。React Strict Mode
仅在开发模式下运行,因此这不会影响您的生产跟踪。
Profiler 选项
withProfiler
高阶组件有多种选项可用于进一步定制。它们可以作为第二个参数传入 withProfiler
函数。
export default Sentry.withProfiler(App, { name: "CustomAppName" });
name
(string)
- 被分析的组件的名称。默认情况下,名称取自组件的
displayName
属性或组件的name
属性。
includeRender
(boolean)
- 是否应该由
Profiler
创建react.render
跨度。默认设置为true
。
includeUpdates
(boolean)
react.update
spans 是否应该由Profiler
创建。默认设置为true
。 对于将经历多次重新渲染的组件(例如文本输入text input
组件),我们建议将此属性设置为false
,因为生成的span
可能非常嘈杂。
配置
基本选项
SDK
可以使用多种选项进行配置。这些选项在 SDK
中基本上是标准化的,但在更好地适应平台特性方面存在一些差异。选项是在 SDK
首次初始化时设置的。
选项作为对象传递给 init()
函数:
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
maxBreadcrumbs: 50,
debug: true,
});
常见选项
跨 SDK
的常用选项列表。这些在所有 SDK
中的工作方式或多或少都相同,但为了更好地支持平台,将存在一些细微差别。 可以从环境变量(SENTRY_DSN
、SENTRY_ENVIRONMENT
、SENTRY_RELEASE
)中读取的选项会自动读取。
dsn
DSN
告诉 SDK
将事件发送到哪里。如果没有提供这个值,SDK
将尝试从 SENTRY_DSN
环境变量中读取它。如果这个变量也不存在,SDK
就不会发送任何事件。
在没有进程环境(如浏览器)的运行时中,fallback
不会应用。
更多:https://docs.sentry.io/product/sentry-basics/dsn-explainer/#dsn-utilization
debug
打开或关闭调试模式。如果启用了调试,如果发送事件时出现问题,SDK
将尝试打印出有用的调试信息。默认值总是 false
。一般不建议在生产环境中打开它,尽管打开 debug
模式不会引起任何安全问题。
release
设置 release。某些 SDK
会尝试自动配置 release
,但是最好手动设置 release
,以确保该 release
与您的 deploy integrations
或 source map uploads
同步。Release
名称是字符串,但是 Sentry
会检测到某些格式,并且它们的呈现方式可能有所不同。
更多:https://docs.sentry.io/product/releases/
默认情况下,SDK
会尝试从环境变量 SENTRY_RELEASE
中读取该值(在浏览器 SDK
中,将从 window.SENTRY_RELEASE
中读取该值,如果可用)。
environment
设置环境。此字符串为自由形式,默认情况下不设置。一个 release
可以与多个环境相关联,以便在 UI 中将它们分开(可以考虑staging
与 prod
或类似的方式)。
默认情况下,SDK
将尝试从 SENTRY_ENVIRONMENT
环境变量中读取该值(浏览器 SDK
除外)。
tunnel
设置将用于传输捕获事件的 URL
,而不是使用 DSN
。这可用于解决广告拦截器(ad-blockers
)或对发送到 Sentry
的事件进行更精细的控制。此选项需要实现自定义服务器端点。
更多:https://docs.sentry.io/platforms/javascript/troubleshooting/#dealing-with-ad-blockers
sampleRate
配置错误事件的采样率,范围为 0.0
到 1.0
。默认值为 1.0
,表示发送了 100%
的错误事件。如果设置为 0.1
,则仅发送 10%
的错误事件。事件是随机选择的。
maxBreadcrumbs
这个变量控制应该捕获的面包屑总数。默认值为 100
。
attachStacktrace
当启用时,堆栈跟踪将自动附加到所有记录的消息。堆栈跟踪总是附加到异常;然而,当设置此选项时,堆栈跟踪也会与消息一起发送。例如,该选项意味着堆栈跟踪显示在所有日志消息的旁边。
该选项默认为 off
。
Sentry
中的分组对于有和没有堆栈跟踪的事件是不同的。因此,当您为某些事件启用或禁用此 flag
时,您将获得新组。
denyUrls
与不应该发送到 Sentry
的错误 URL
相匹配的字符串或正则表达式模式列表。默认情况下,将发送所有错误。这是一个 “contains(包含)” 匹配整个文件 URL。因此,如果你添加 foo.com
,它也会匹配 https://bar.com/myfile/foo.com
。默认情况下,将发送所有错误。
allowUrls
匹配错误 URL
的字符串列表或正则表达式模式的遗留别名,这些错误 URL
应该专门发送给 Sentry
。默认情况下,将发送所有错误。这是一个 “contains(包含)” 匹配整个文件 URL。因此,如果您将 foo.com
添加到它,它也将匹配 https://bar.com/myfile/foo.com
。默认情况下,所有错误将被发送。
autoSessionTracking
设置为 true
时,SDK
将向 Sentry
发送 session
事件。这在所有浏览器 SDK
中都受支持,每个页面加载和页面导航都向 Sentry
发出一个 session
。在移动 SDK
中,当应用进入后台超过 30
秒时,会话结束。
initialScope
要设置为初始作用域的数据。初始作用域可以定义为对象或回调函数,如下所示。
对象:
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
debug: true,
initialScope: {
tags: {"my-tag": "my value"},
user: {id: 42, email: "john.doe@example.com"},
}
});
回调函数:
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
debug: true,
initialScope: scope => {
scope.setTags({ a: 'b' });
return scope;
},
});
maxValueLength
单个值在被截断之前可以具有的最大字符数(默认为 250
)。
normalizeDepth
Sentry SDK
将任何上下文数据标准化到给定的深度。 任何包含结构比这更深的数据的 key
都将使用其类型([Object]
或 [Array]
)进行修剪和标记,而不会进一步遍历树。默认情况下,步行执行 3
级深度。
集成配置
对于许多平台,SDK 集成可以与之一起配置。在一些平台上,这是 init()
调用的一部分,而在另一些平台上,则应用不同的模式。
integrations
在某些 SDK 中,在库初始化时通过此参数配置集成。
更多:
defaultIntegrations
这可以用来禁用默认添加的集成。当设置为 false
时,不会添加默认的集成。
Hooks
这些选项可用于以各种方式 hook SDK
,以定制事件的报告。
beforeSend
使用 SDK-specific
事件对象调用此函数,可以返回修改后的事件对象或不返回任何内容,以跳过报告事件。例如,这可以用于在发送前手动剥离 PII
。
beforeBreadcrumb
在将面包屑添加到作用域之前,使用 SDK
特定的面包屑(SDK-specific breadcrumb
)对象调用此函数。当该函数未返回任何内容时,将删除 breadcrumb
。要传递 breadcrumb
,请返回第一个参数,其中包含 breadcrumb
对象。回调通常会获得第二个参数(称为“hint”
),该参数包含创建 breadcrumb
的原始对象,以进一步自定义面包屑的外观。
传输选项
Transports
被用来发送事件到 Sentry
。可以在某种程度上对传输进行定制,以更好地支持高度特定的部署。
transport
切换出用于发送事件的 transport
。如何运作取决于 SDK
。例如,它可以用于捕获事件以进行单元测试,或通过需要代理身份验证的更复杂的设置发送事件。
跟踪选项
tracesSampleRate
0
到 1
之间的数字,控制给定事务发送到 Sentry
的概率百分比。(0
表示 0%
,1
表示 100%
)同样适用于应用程序中创建的所有事务。必须定义这个或 tracesSampler
以启用跟踪。
tracesSampler
一个函数负责确定一个给定的事务将被发送到 Sentry
的概率百分比。它将自动被传递有关事务和创建它的上下文的信息,并且必须返回一个介于 0
(被发送的概率为 0%
)和 1
(被发送的概率为 100%
) 之间的数字。还可以用于过滤事务,对不需要的事务返回 0
。必须定义这个或 tracesSampleRate
来启用跟踪。
集成
默认集成
Sentry
的所有 SDK
都提供集成,可扩展 SDK
的功能。
默认情况下启用系统集成以集成到标准库或解释器本身。 它们被记录在案,因此您既可以了解它们的作用,也可以在它们引起问题时禁用它们。
默认启用
InboundFilters
Import name: Sentry.Integrations.InboundFilters
通过这种集成,您可以根据给定异常中的类型,消息或 URL 忽略特定错误。
默认情况下,它忽略以 Script error
或 Javascript error: Script error
开头的错误。
要配置这个集成,直接使用 ignoreErrors
,denyUrls
,和 allowUrls
SDK 选项。请记住,denyURL
和 allowURL
只对捕获的异常有效,而不是原始消息事件。
FunctionToString
Import name: Sentry.Integrations.FunctionToString
这种集成使 SDK
可以提供原始的函数和方法名称,即使我们的错误(error
)或面包屑处理程序(breadcrumbs handlers
)包装了它们也是如此。
TryCatch
Import name: Sentry.Integrations.TryCatch
这个集成封装了原生 time
和 events APIs
(setTimeout
, setInterval
, requestAnimationFrame
, addEventListener/removeEventListener
) 在 try/catch
块处理 async
异常。
Breadcrumbs
Import name: Sentry.Integrations.Breadcrumbs
这种集成封装了原生 API 以捕获面包屑。默认情况下,Sentry SDK
封装了所有 API
。
可用选项:
{
// 记录对 `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;
}
GlobalHandlers
Import name: Sentry.Integrations.GlobalHandlers
这个集成附加了全局处理程序来捕获未捕获的 exceptions
和未处理的 rejections
。
可用的选项:
{
onerror: boolean;
onunhandledrejection: boolean;
}
LinkedErrors
Import name: Sentry.Integrations.LinkedErrors
此集成允许您配置 linked
错误。它们将被递归地读取到指定的限制,并由特定的 key
执行查找。默认情况下,Sentry SDK
将限制设置为 5
,使用的键 key
是 cause
。
可用的选项:
{
key: string;
limit: number;
}
这是如何实现的代码示例:
document
.querySelector("#get-reviews-btn")
.addEventListener("click", async event => {
const movie = event.target.dataset.title;
try {
const reviews = await fetchMovieReviews(movie);
renderMovieReviews(reviews);
} catch (e) {
const fetchError = new Error(`Failed to fetch reviews for: ${movie}`);
fetchError.cause = e;
Sentry.captureException(fetchError);
renderMovieReviewsError(fetchError);
}
});
UserAgent
Import name: Sentry.Integrations.UserAgent
这种集成将 user-agent
信息附加到事件中,这使我们能够正确地分类并使用特定的操作系统(OS
),浏览器(browser
)和版本(version
)信息对其进行标记。
Dedupe
Import name: Sentry.Integrations.Dedupe
这种集成消除了某些事件的重复数据。如果您收到许多重复的错误,这会很有帮助。请注意,Sentry
只会比较堆栈跟踪(stack traces
)和指纹(fingerprints
)。默认情况下为浏览器启用此集成。
import * as Sentry from "@sentry/browser";
import { Dedupe as DedupeIntegration } from "@sentry/integrations";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
integrations: [new DedupeIntegration()],
});
CDN
<script
src="https://browser.sentry-cdn.com/6.12.0/bundle.min.js"
integrity="sha384-S3qfdh3AsT1UN84WIYNuOX9vVOoFg3nB17Jp5/pTFGDBGBt+dtz7MGAV845efkZr"
crossorigin="anonymous"
></script>
<script
src="https://browser.sentry-cdn.com/6.12.0/dedupe.min.js"
integrity="sha384-3IMGY+DN27Yns7KDiKL3sOWXBYlILQ/bxLogt02NG7DL7qEJHIMbpnXfqNlO0J8G"
crossorigin="anonymous"
></script>
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
integrations: [new Dedupe()],
});
修改系统集成
要禁用系统集成,请在调用 init()
时设置 defaultIntegrations: false
。
要覆盖它们的设置,请提供一个带有您的配置到集成选项的新实例。 例如,要关闭浏览器捕获控制台调用:integrations: [new Sentry.Integrations.Breadcrumbs({ console: false })]
。
删除集成
此示例删除了用于向事件添加面包屑的默认启用集成:
Sentry.init({
// ...
integrations: function(integrations) {
// integrations will be all default integrations
return integrations.filter(function(integration) {
return integration.name !== "Breadcrumbs";
});
},
});
可插拔集成
这些可插拔的集成是为特定的应用程序和/或框架增加功能的代码片段。我们对它们进行了记录,这样您就可以看到它们的功能,并且可以启用它们。
如何启用
安装 @sentry/integrations
包,并提供一个带有你配置到 integrations
选项的新实例。加载 SDK
之后,包括插件。
示例:
import * as Sentry from "@sentry/browser";
import { ReportingObserver as ReportingObserverIntegration } from "@sentry/integrations";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
integrations: [new ReportingObserverIntegration()],
});
CDN
<script
src="https://browser.sentry-cdn.com/6.12.0/bundle.min.js"
integrity="sha384-S3qfdh3AsT1UN84WIYNuOX9vVOoFg3nB17Jp5/pTFGDBGBt+dtz7MGAV845efkZr"
crossorigin="anonymous"
></script>
<script
src="https://browser.sentry-cdn.com/6.12.0/reportingobserver.min.js"
integrity="sha384-20D83MPBNSRANJFguhj0o9Qo7p9MCemwdMMQXotwA8742WuIwga85k+T7qEgIMWK"
crossorigin="a