检测 Sentry.captureMessage(...) 或 Sentry.captureException(...) 是否在 JavaScript 应用中被阻止(例如,被广告拦截器阻止)

Detect if Sentry.captureMessage(…) or Sentry.captureException(…) gets blocked in an JavaScript app (e.g. by an ad blocker)

提问人:DerZyklop 提问时间:10/26/2023 更新时间:10/27/2023 访问量:98

问:

设置

我们有一个 Javascript (Angular/TypeScript) 应用程序,它使用 Sentry.io 进行错误报告。

如果发生抛出,全局错误处理程序会处理并向用户显示带有 textarea 的自定义模式,以便用户可以在那里留言。当 Sentry 单击提交按钮时,应将此消息发送给 Sentry(通过 Sentry.captureMessage(...))。

问题

最近我们发现,如果无法访问 Sentry,我们就不会收到这些消息,因为它被广告拦截器浏览器插件阻止。

目标

我们想做以下解决方案之一:

  • 如果 Sentry 有任何问题,只需向用户提供如何获得支持的说明,而不是提供通过 Sentry 给我们写消息的可能性。
  • 提供通过 Sentry 给我们写消息的可能性,但如果发送此消息失败,请向用户提供说明,之后如何获得支持。

我们尝试过的事情

我们检查了是否提供了任何帮助,因为它是发送 POST 请求的那个。但是,无论请求是否成功,它都会返回 eventId。包装到 try/catch 中无济于事,因为它不会在请求不成功时抛出。Sentry.captureMessage(…)Sentry.captureMessage(…)

之后还有一个 ,但返回的是,如果所有事件都已发送,则无论成功与否。Sentry.captureMessage(…)Sentry.flush(…)Promise<boolean>true

我们现在所做的是深入挖掘 Sentry 的内部结构,这些内部结构并不意味着从外部使用。在这里,我们实现了一个方法,如果 Sentry 被阻止,则返回该方法,如果 Sentry 被阻止,则返回该方法。truefalse

public sentryIsBlocked() : boolean | null {
    const client = Sentry.getCurrentHub().getClient();

    // If there is no client, we can not check if sentry is reachable
    if (!client) return null;

    // This would be a TS error, because what we ask for is not public information.
    // So we cast to any to work around that.
    const numberOfNetworkSessionErrors = (client as any)['_outcomes']['network_error:session'];

    return !!numberOfNetworkSessionErrors && numberOfNetworkSessionErrors > 0;
}

到目前为止,它有效,但是......

这种方法的缺点
  • 任何 Sentry 更新都可能破坏它,因为我们使用的对象不属于 Sentry 的公共 API。
  • 如果过去向哨兵提出的任何请求有问题,我们就会明白这一点,但这并不一定意味着当前的请求不会通过。

问题

有没有办法跟踪 POST 请求是否从 发送或返回错误?Sentry.captureMessage(…)Sentry.captureException(…)

TypeScript XMLhttpRequest 哨兵 HTTP 错误 adblock

评论


答:

1赞 Bruno Garcia 10/26/2023 #1

Sentry 提供了一个选项,可以通过您自己的后端隧道传输数据。以下是有关此内容的文档: https://docs.sentry.io/platforms/javascript/troubleshooting/#using-the-tunnel-option

这样,SDK 会将数据发送到后端的终结点。这之所以有效,是因为广告拦截器通常会列出哨兵的摄取端点。

下面是 NuGet 趋势应用上的隧道示例。使用终结点 /t

在后端,如果您将 Sentry 用于 ASP.NET Core,则可以使用 1 行添加它:

https://github.com/dotnet/nuget-trends/blob/3b12f722505aca5423e469449549e46ab4986f6c/src/NuGetTrends.Web/Startup.cs#L120

app.UseSentryTunneling("/t");

客户端的配置:

tunnel: “/t”

巧合的是,Angular 也 https://github.com/dotnet/nuget-trends/blob/3b12f722505aca5423e469449549e46ab4986f6c/src/NuGetTrends.Web/Portal/src/app/app.module.ts#L22