提问人:DerZyklop 提问时间:10/26/2023 更新时间:10/27/2023 访问量:98
检测 Sentry.captureMessage(...) 或 Sentry.captureException(...) 是否在 JavaScript 应用中被阻止(例如,被广告拦截器阻止)
Detect if Sentry.captureMessage(…) or Sentry.captureException(…) gets blocked in an JavaScript app (e.g. by an ad blocker)
问:
设置
我们有一个 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 被阻止,则返回该方法。true
false
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(…)
答:
Sentry 提供了一个选项,可以通过您自己的后端隧道传输数据。以下是有关此内容的文档: https://docs.sentry.io/platforms/javascript/troubleshooting/#using-the-tunnel-option
这样,SDK 会将数据发送到后端的终结点。这之所以有效,是因为广告拦截器通常会列出哨兵的摄取端点。
下面是 NuGet 趋势应用上的隧道示例。使用终结点 /t
在后端,如果您将 Sentry 用于 ASP.NET Core,则可以使用 1 行添加它:
app.UseSentryTunneling("/t");
客户端的配置:
tunnel: “/t”
评论