Sentry For React 完整接入详解(2021 Sentry v21.8.x)前方高能预警!三万字,慎入!

内容源于:https://docs.sentry.io/platforms/javascript/guides/react/

系列

脑图

公众号:黑客下午茶

快速开始

SentryReact 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)

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)生成 spanreact.mountreact.renderreact.update

react.mount

  • 表示被分析组件 mount 所需时间的跨度。

react.render

  • 表示被分析组件在页面上的时间跨度。只有在事务发生时 mountunmount 被分析的组件时,才会生成这个跨度。

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_DSNSENTRY_ENVIRONMENTSENTRY_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 integrationssource map uploads 同步。Release 名称是字符串,但是 Sentry 会检测到某些格式,并且它们的呈现方式可能有所不同。

更多:https://docs.sentry.io/product/releases/

默认情况下,SDK 会尝试从环境变量 SENTRY_RELEASE 中读取该值(在浏览器 SDK 中,将从 window.SENTRY_RELEASE 中读取该值,如果可用)。

environment

设置环境。此字符串为自由形式,默认情况下不设置。一个 release 可以与多个环境相关联,以便在 UI 中将它们分开(可以考虑stagingprod 或类似的方式)。

默认情况下,SDK 将尝试从 SENTRY_ENVIRONMENT 环境变量中读取该值(浏览器 SDK 除外)。

tunnel

设置将用于传输捕获事件的 URL,而不是使用 DSN。这可用于解决广告拦截器(ad-blockers)或对发送到 Sentry 的事件进行更精细的控制。此选项需要实现自定义服务器端点。

更多:https://docs.sentry.io/platforms/javascript/troubleshooting/#dealing-with-ad-blockers

sampleRate

配置错误事件的采样率,范围为 0.01.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

01 之间的数字,控制给定事务发送到 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 errorJavascript error: Script error 开头的错误。

要配置这个集成,直接使用 ignoreErrorsdenyUrls,和 allowUrls SDK 选项。请记住,denyURLallowURL 只对捕获的异常有效,而不是原始消息事件。

FunctionToString

Import name: Sentry.Integrations.FunctionToString

这种集成使 SDK 可以提供原始的函数和方法名称,即使我们的错误(error)或面包屑处理程序(breadcrumbs handlers)包装了它们也是如此。

TryCatch

Import name: Sentry.Integrations.TryCatch

这个集成封装了原生 timeevents APIs (setTimeout, setInterval, requestAnimationFrame, addEventListener/removeEventListener) 在 try/catch 块处理 async 异常。

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,使用的键 keycause

可用的选项:

{
  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
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值