作用域

SDK 通常会在框架集成中自动管理作用域。了解什么是作用域以及如何利用它来获得优势。

当事件被捕获并发送到 Sentry 时,SDK 会将事件数据与当前作用域的额外信息合并。SDK 通常会在框架集成中自动管理作用域,因此你不需要特别考虑它们。然而,你应该了解什么是作用域以及如何利用它来获得优势。

作用域保存了随事件一起发送的有用信息。例如,上下文面包屑 都存储在作用域中。当一个作用域被分叉时,它会继承其父作用域的所有数据。

默认的 SDK 集成会智能地分叉作用域。例如,Web 框架集成会在你的路由或请求处理程序周围分叉作用域。

作用域基本上是附加到事件的数据栈。当事件被捕获时,SDK 会将活动作用域中的数据合并到事件中。这允许你将与捕获事件的上下文相关的信息附加到事件上。

作用域通常在回调或执行上下文中有效。这意味着你的应用程序的不同部分可能同时有不同的作用域处于活动状态。例如,Web 服务器可能会同时处理多个请求,每个请求可能有不同的作用域数据应用于其事件。

Sentry SDK 有三种不同类型的作用域:

全局作用域应用于 所有 事件,无论它们来自何处。你可以用它来存储应应用于所有事件的数据,例如环境信息。

你可以通过 Sentry.getGlobalScope() 访问全局作用域。

注意,全局作用域只能用于写入数据,不能用于捕获事件。事件只能在当前作用域上捕获(例如,getCurrentScope().captureException() 和类似的 API)。

隔离作用域用于隔离事件,使它们互不干扰。例如,Web 服务器中的每个请求可能有自己的隔离作用域,以确保一个请求的事件不会干扰另一个请求的事件。在大多数情况下,你应该将应应用于事件的数据放在隔离作用域上。这就是为什么所有的 Sentry.setXXX 方法(如 Sentry.setTag())会将数据写入当前活跃的隔离作用域。一个典型的例子是用户数据,因为每个请求可能有不同的用户,所以你需要确保用户数据设置在隔离作用域上。

你可以通过 Sentry.getIsolationScope() 访问隔离作用域,但通常你会使用 Sentry.setXXX 方法将数据设置在当前活跃的隔离作用域上:

Copied
Sentry.setTag("my-tag", "my value");
// Is identical to:
Sentry.getIsolationScope().setTag("my-tag", "my value");

注意,隔离作用域只能用于写入数据,不能用于捕获事件。事件只能在当前作用域上捕获(例如,getCurrentScope().captureException() 和类似的 API)。

当前作用域是当前活跃的本地作用域。与很少分叉的隔离作用域不同,当前作用域可能会更频繁地在内部分叉。它可以用于存储仅应应用于特定事件的数据。

Copied
Sentry.withScope((scope) => {
  // scope is the current scope inside of this callback!
  scope.setTag("my-tag", "my value");
  // this tag will only be applied to events captured inside of this callback
  // the following event will have the tag:
  Sentry.captureException(new Error("my error"));
});
// this event will not have the tag:
Sentry.captureException(new Error("my other error"));

你可以通过 Sentry.getCurrentScope() 访问当前作用域,但在大多数情况下,你应该使用 Sentry.withScope() 来与本地作用域交互。

在事件(如错误或事务)发送到 Sentry 之前,当前活跃的作用域会被应用到事件上。

首先应用全局作用域,然后是隔离作用域,最后是当前作用域。这意味着事件会依次继承这些作用域中的数据。每个作用域的数据会合并到事件中,确保事件包含所有相关的上下文信息。

Copied
Sentry.getGlobalScope().setExtras({
  shared: "global",
  global: "data",
});
Sentry.getIsolationScope().setExtras({
  shared: "isolation",
  isolation: "data",
});
Sentry.getCurrentScope().setExtras({
  shared: "current",
  current: "data",
});

Sentry.captureException(new Error("my error"));
// --> Will have the following extra:
// { shared: 'current', global: 'data', isolation: 'data', current: 'data' }

与作用域交互主要有两种方式。你可以通过 Sentry.getCurrentScope() 访问当前作用域,并在返回的作用域上使用设置方法,或者你可以直接使用全局方法如 Sentry.setTag(),这些方法会在底层设置到相应的作用域(这将是隔离作用域)。

首先需要像往常一样导入 SDK:

Copied
import * as Sentry from "@sentry/browser";

例如,你可以添加自定义标签或告知 Sentry 当前已认证的用户。

Copied
/// Usually, you don't want to write on the current scope, so use with care!
const scope = Sentry.getCurrentScope();
scope.setTag("my-tag", "my value");
scope.setUser({
  id: 42,
  email: "john.doe@example.com",
});

// Or use the global methods (which will set data on the isolation scope):
Sentry.setTag("my-tag", "my value");
Sentry.setUser({
  id: 42,
  email: "john.doe@example.com",
});

要了解可以与作用域关联的有用信息,请参阅 上下文标签用户面包屑

在以下示例中,我们使用 withScope 仅将一个特定错误附加一个 level 和一个 tag

Copied
Sentry.withScope(function (scope) {
  scope.setTag("my-tag", "my value");
  scope.setLevel("warning");
  // will be tagged with my-tag="my value"
  Sentry.captureException(new Error("my error"));
});

// will not be tagged with my-tag
Sentry.captureException(new Error("my other error"));

withScope() 回调内的作用域仅在回调内部有效。一旦回调结束,作用域将被移除且不再应用。内部作用域仅应用于在回调内捕获的事件。withScope() 会克隆(或分叉)当前作用域,因此当前作用域不会被修改。这使你可以更轻松地将上下文信息隔离到代码中的特定位置,甚至可以调用 clear 短暂移除所有上下文信息。