获取更多动态,关注公众号:黑客下午茶

Troubleshooting

如果您需要有关 Sentry JavaScript SDK 集成的解决 issues 的帮助,则可以阅读此处记录的一些案例。如果您需要其他帮助,则可以查看我们的论坛,付费计划的客户也可以与客户支持人员联系。

Debugging Additional Data

您可以查看事件的 JSON payload,以了解 Sentry 如何在事件中存储其他数据。数据的形状可能与描述不完全匹配。

Red box highlighting where to find the JSON connected to an event

有关详细信息,请参阅关于 Event Payload 文档

Max JSON Payload Size

maxValueLength 的默认值为 250,但是如果您的消息较长,则可以根据需要调整此值。请注意,并非每个单个值都受此选项影响。

CORS Attributes and Headers

要了解来自不同来源的脚本引发的 JavaScript 异常,请执行以下两项操作:

  1. 添加一个 crossorigin=”anonymous” 脚本属性
Copied
 <script src="http://another-domain.com/app.js" crossorigin="anonymous"></script>

script 属性告诉浏览器 “anonymously” 地获取目标文件。当请求此文件时,潜在的用户识别信息(如 cookie 或 HTTP 凭据)不会被浏览器传输到服务器。

  1. 添加一个 Cross-Origin HTTP header
Copied
Access-Control-Allow-Origin: *

跨域资源共享(CORS)是一组 API(主要是 HTTP headers),这些 API 决定了应如何跨源下载和服务文件。

通过设置 Access-Control-Allow-Origin: *,服务器向浏览器指示任何来源都可以获取该文件。另外,您可以将其限制为您控制的已知来源:

Copied
 Access-Control-Allow-Origin: https://www.example.com

大多数社区 CDN 正确设置了 Access-Control-Allow-Origin 标头。

Copied
 $ curl --head https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.js | \
 grep -i "access-control-allow-origin"

 Access-Control-Allow-Origin: *

instrument.js Line Numbers for Console Log statements

如果在调试时在控制台显示 instrument.js,添加 Sentry 到你的框架 blackboxing ,设置如下:/@sentry/,这样 Chrome 在调试时忽略 SDK stackframes。

Dealing with Ad-Blockers

当您使用我们的 CDN 时,广告拦截(ad-blocking)或脚本拦截(script-blocking)扩展程序可能会阻止我们的 SDK 无法正确获取和初始化。因此,对 SDKs API 的任何调用都将失败,并可能导致您的应用程序行为异常。如果这适用于您的用例,则以下任何一种解决方案都可以缓解此问题。

处理脚本阻止扩展的最好方法是直接通过 npm 使用SDK软件包,并将其与您的应用程序捆绑在一起。这样,您可以确保代码将始终如您所愿地存在。

第二种方法是从 CDN 下载 SDK 并自己托管。这样,SDK 仍将与您的其余代码分开,但是您可以确定它不会被阻止,因为它的来源与您网站的来源相同。

您可以使用 curl 或任何其他类似的工具轻松获取它:

Copied
curl https://browser.sentry-cdn.com/5.20.1/bundle.min.js -o sentry.browser.5.20.1.min.js -s

最后一个选项是使用 Proxy 防护,即使您调用被阻止的 SDK,也可以确保您的代码不会中断。除 Internet Explorer 之外,所有浏览器均支持 Proxy,尽管该浏览器没有扩展。同样,如果您的用户浏览器中没有安装 Proxy,它也会被静默跳过,因此您不必担心它会破坏任何东西。

将此片段放在包含我们的 CDN bundle 软件的 <script> 标记上方。可读格式的代码段显示如下:

Copied
if ("Proxy" in window) {
  var handler = {
    get: function(_, key) {
      return new Proxy(function(cb) {
        if (key === "flush" || key === "close") return Promise.resolve();
        if (typeof cb === "function") return cb(window.Sentry);
        return window.Sentry;
      }, handler);
    },
  };
  window.Sentry = new Proxy({}, handler);
}

如果你想直接复制和粘贴代码片段,这里是缩小过后的:

Copied
<script>
  if ("Proxy" in window) {
    var n = {
      get: function(o, e) {
        return new Proxy(function(n) {
          return "flush" === e || "close" === e
            ? Promise.resolve()
            : "function" == typeof n
            ? n(window.Sentry)
            : window.Sentry;
        }, n);
      },
    };
    window.Sentry = new Proxy({}, n);
  }
</script>

Using a Client directly

为了能够管理多个 Sentry 实例而彼此之间没有任何冲突,您需要创建自己的 Client。如果您的应用程序集成在其中,这也有助于防止跟踪任何父应用程序错误。在此示例中,我们使用 @sentry/browser,但它也适用于 @sentry/node

Copied
import { BrowserClient } from "@sentry/browser";

const client = new BrowserClient({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
});

client.captureException(new Error("example"));

尽管上面的示例工作得很好,但是 Client 上缺少诸如 configureScopewithScope 的某些方法,因为 Hub 负责状态管理。这就是为什么创建一个新的 Hub 并将其 Client 绑定到它上可能更容易的原因。结果是相同的,但是您还将获得状态管理。

Copied
import { BrowserClient, Hub } from "@sentry/browser";

const client = new BrowserClient({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
});

const hub = new Hub(client);

hub.configureScope(function(scope) {
  scope.setTag("a", "b");
});

hub.addBreadcrumb({ message: "crumb 1" });
hub.captureMessage("test");

try {
  a = b;
} catch (e) {
  hub.captureException(e);
}

hub.withScope(function(scope) {
  hub.addBreadcrumb({ message: "crumb 2" });
  hub.captureMessage("test2");
});

Dealing with integrations

Integrations 是在 Client 上设置的,如果你需要处理多个 clients 和 hubs,你必须确保也正确地进行集成处理。下面是一个工作示例,演示如何使用多个 clients 和多个 hubs 运行全局集成。

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

// Very happy integration that'll prepend and append very happy stick figure to the message
class HappyIntegration {
  constructor() {
    this.name = "HappyIntegration";
  }

  setupOnce() {
    Sentry.addGlobalEventProcessor(event => {
      const self = Sentry.getCurrentHub().getIntegration(HappyIntegration);
      // Run the integration ONLY when it was installed on the current Hub
      if (self) {
        event.message = `\\o/ ${event.message} \\o/`;
      }
      return event;
    });
  }
}

HappyIntegration.id = "HappyIntegration";

const client1 = new Sentry.BrowserClient({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [...Sentry.defaultIntegrations, new HappyIntegration()],
  beforeSend(event) {
    console.log("client 1", event);
    return null; // Returning null does not send the event
  },
});
const hub1 = new Sentry.Hub(client1);

const client2 = new Sentry.BrowserClient({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0", // Can be a different DSN
  integrations: [...Sentry.defaultIntegrations, new HappyIntegration()],
  beforeSend(event) {
    console.log("client 2", event);
    return null; // Returning null does not send the event
  },
});
const hub2 = new Sentry.Hub(client2);

hub1.run(currentHub => {
  // The hub.run method makes sure that Sentry.getCurrentHub() returns this hub during the callback
  currentHub.captureMessage("a");
  currentHub.configureScope(function(scope) {
    scope.setTag("a", "b");
  });
});

hub2.run(currentHub => {
  // The hub.run method makes sure that Sentry.getCurrentHub() returns this hub during the callback
  currentHub.captureMessage("x");
  currentHub.configureScope(function(scope) {
    scope.setTag("c", "d");
  });
});

Third Party Promise Libraries

当您包含并配置 Sentry 时,我们的 JavaScript SDK 会自动将 global handlers 附加到 capture 未捕获的 exceptions 和未处理的 promise rejections。您可以通过在 GlobalHandlers 集成中将 onunhandledrejection 选项设置为 false 来禁用此默认行为,并手动挂钩到每个事件 handler,然后直接调用 Sentry.captureExceptionSentry.captureMessage

如果您使用第三方库来实现 promises,则可能还需要管理您的配置。另外,请记住,浏览器经常实施安全措施,当提供来自不同来源的脚本文件时,这些措施会阻止错误报告。

You can edit this page on GitHub.