Sentry-javascript: 离线报告的方向?

创建于 2014-10-31  ·  27评论  ·  资料来源: getsentry/sentry-javascript

嗨,我们有一个部署了离线功能的 Web 应用程序,使用 Sentry 进行应用程序监控会很棒。 我们已经将它用于我们的后端,而且效果很好!

不幸的是,我在 raven js 中没有看到对此的支持,所以我认为我们将被迫推出我们自己的解决方案。 你能证实这一点吗? 您对如何进行有什么建议? 您会建议尝试重用 raven js 中的一些逻辑吗?

最有用的评论

我们的解决方案:

shouldSendCallback传递给 Raven init

如果没有连接,out logStorageService 将保存事件的数据

var options = {
    ...
    shouldSendCallback: function(data) {
        if (connectionStatus.check() && Raven.isSetup()) {
            return true;
        } else {
            // store log data somewhere
            logStorageService.set(data);
            return false;
        }
    }
    ...
};

Raven.config(SENTRY_KEY, options).install();

队列试图发送日志

Queue 每 25 秒触发一次此代码,最终将所有事件传递给 Sentry

queue.enqueue(function () {
                    logStorageService
                        .getKeys()
                        .then(function (keys) {
                            if (keys && keys[0]) {
                                logStorageService
                                    .get(keys[0])
                                    .then(function (log) {
                                        Raven.captureMessage('', log);
                                        logStorageService.remove(keys[0]);
                                    });
                            }
                            ...
                        });
                });

所有27条评论

你能检测到用户是否离线吗?

如果是这样,收集事件并将它们排队也不是不可能的。 当用户重新上线时,再次通过Raven.captureException向他们发送。

我可能可以帮助解决它的工作原理或添加一个钩子来帮助解决这个问题。

太好了,谢谢合作。 即使只是测试 Sentry 可达性,我也可以检测到用户在线。 为此,我可以侦听传输失败事件,但是如何重试?

关于使用captureException ,这很好,但我想保留优秀的处理程序 raven 为未处理的异常提供。 我需要在 raven 错误检测和错误传输之间添加一些中间逻辑

是的,让我想想这个。 我认为有一个很好的方法,我们可以在 raven-js 中自动支持它,或者提供一个钩子来做到这一点。 我认为这很公平。

我也在寻找相同的功能。 在检查了文档后,似乎可以使用shouldSendCallback ,如下所示:

shouldSendCallback: function(data) {
  localStorage['queued-errors'] = (localStorage['queued-errors'] || []).push(data);
  return false;
}

然后监听网络连接并使用Raven.captureException处理队列:

window.addEventListener('online', checkAndProcessQueue);

这有点捎带,但我有类似的问题。 当客户端失去与主机的连接时,我们无法报告错误(尽管它们不一定离线)。 四处游荡,我看到在窗口上触发了ravenFailure事件,但我无法从该事件中获取足够的数据来完成我想要做的事情:在失败时重试发送错误。

我看到了一些可能的方法:

  1. 每个实例或每个消息retry选项,它可能指定重试发送事件的频率,在放弃之前尝试多少次等。
  2. 在成功/失败时触发的captureException(), sendMessage()` 等方法上的回调/回调
  3. 承诺这些方法(meh)
  4. 在失败时触发事件(在哪里?)并在事件数据中提供足够的上下文以尝试重新发送该事件

您可能应该有一个离线存储设施,以便稍后可以发送错误消息。 可能甚至在用户关闭应用程序并稍后在在线时重新打开它之后。 类似于“离线优先”的方法:
http://offlinefirst.org/

我遇到了同样的问题。 起初,我想解决它类似于我如何解决离线 google-analytics 问题与service worker 。 谷歌在这里很好地解释了这种方法。

但是,当以 Cordova 为目标时,Service Worker 可能不可用。
并且需要一个 _hacky_解决方案。 我想出了这个:

https://gist.github.com/oliviertassinari/73389727fe58373eef7b63d2d2c5ce5d

import raven from 'raven-js';
import config from 'config';

const SENTRY_DSN = 'https://[email protected]/YYYY';

function sendQueue() {
  const sentryOffline = JSON.parse(window.localStorage.sentryOffline);

  if (sentryOffline.length > 0) {
    raven._send(sentryOffline[0]);
  }
}

// ... 

我同意@webberig。 我实际上有点惊讶这还不是 raven 的一部分,因为它在很多其他很酷的方面都令人印象深刻。 根据应用程序的架构,可能有相当比例的错误是离线的结果。 在许多实现中,能够报告这些是非常重要的。

所以我的投票是这应该是自动的。 当将消息发送到 sentry 时出现错误时,应该存储该消息并稍后重试(在计时器上、在事件上,或者甚至只是在下一个消息传输上,如果您想保持简单的话)。

另外,“DDN”标签是什么意思?

我实际上有点惊讶这还不是 raven 的一部分,因为它在很多其他很酷的方面都令人印象深刻。 根据应用程序的架构,可能有相当比例的错误是离线的结果。

完全公平。 但我不确定它是否应该默认完成。 在许多情况下,如果脚本未加载,应用程序无论如何都无法运行。 而且我会说大多数应用程序直接不能离线工作,也不要指望。 这是否是好的做法是另一回事。

这就是为什么我们默认不记录 AJAX 错误的原因,即使大量 Raven 用户已经编写了代码来这样做。 但是,如果您愿意,我们会尽量简化操作。 我想在这里做同样的事情。

另外,“DDN”标签是什么意思?

不确定。 @mattrobenolt?

需要设计决策。 :)

我不确定它是否应该在默认情况下完成。

是的,这是有道理的。

但是,如果您愿意,我们会尽量简化操作。 我想在这里做同样的事情。

因此,为了帮助做出设计决策,这里有一些想法:

如果我正确理解文档transport配置选项允许人们基本上控制管道的最后一部分,哨兵将数据发送到服务器并负责进行传输。 在这种情况下,这似乎是插入离线队列的最佳位置。 不是将数据发送到服务器,而是将其发送到在后台上传到服务器的队列。 那就是如果有人编写自己的代码来实现它。

以类似的方式,公开一个配置选项( includeOffline ?)是否足够简单,它将用官方 Raven-rolled 离线队列替换默认 HTTP 传输?

  • 为了浏览器兼容性,可以将队列存储在 localStorage 中并让它在超时时检查连接。
  • 为了更好的性能和稳定性,也许可以利用 service workers 来管理队列,这样甚至可以在页面关闭后上传错误。 但是,在这一点上,实用程序库启动自己的服务工作者是否有点冒昧?

现在是否以某种方式内置了此功能以供 raven 使用?

@Freundschaft不,还没有。 据我了解,现在您必须覆盖transport选项或使用shouldSendCallback构建一个队列以供稍后发送。

@cudasteve谢谢!
有人有一个有效的示例实现吗? 如果没有,我会尝试写一个并张贴在这里

@Freundschaft这将非常有帮助。 我们面临同样的问题

++1 请

+1

+1

我们的解决方案:

shouldSendCallback传递给 Raven init

如果没有连接,out logStorageService 将保存事件的数据

var options = {
    ...
    shouldSendCallback: function(data) {
        if (connectionStatus.check() && Raven.isSetup()) {
            return true;
        } else {
            // store log data somewhere
            logStorageService.set(data);
            return false;
        }
    }
    ...
};

Raven.config(SENTRY_KEY, options).install();

队列试图发送日志

Queue 每 25 秒触发一次此代码,最终将所有事件传递给 Sentry

queue.enqueue(function () {
                    logStorageService
                        .getKeys()
                        .then(function (keys) {
                            if (keys && keys[0]) {
                                logStorageService
                                    .get(keys[0])
                                    .then(function (log) {
                                        Raven.captureMessage('', log);
                                        logStorageService.remove(keys[0]);
                                    });
                            }
                            ...
                        });
                });

上面的一些示例显示了对“私有”函数的调用。 但是,我无法调用Raven._sendProcessedPayloadRaven._send

查看您的源代码,我什至不确定 Raven() 是如何构建为对象的。 我在任何地方都看不到“new Raven()”。

如何调用这些函数?

没关系,问题只发生在raven.min.js而不是raven.js因此可以回答这个问题。

所以,我找到了_sendProcessedPayload函数的缩小名称,这是我在代码中得到的结果(目前):

  /**
   * HACK: Using a private function that gets minified!
   * Pinned Raven-js to version 3.8.1.
   */
  Raven._sendProcessedPayload = Raven._sendProcessedPayload || Raven.Y;

  ...

  function processQueue(items) {
    // Stop if we're not online.
    if (!canSend())
      return;
    // Process the given items or get them from the queue.
    items = items || queue.getItems();
    if (!items || items.length < 1)
      return;
    // First in, first out.
    var next = items.shift();
    // Send the next item.
    Raven._sendProcessedPayload(next, function processed(error) {
      // If no errors, save the queue and process more items.
      if (!error) {
        queue.save(items);
        processQueue(items);
      }
    });
  }

  function shouldSend(data) {
    if (canSend())
      return true;
    if (data.extra.retry)
      return false;
    data.extra.retry = true;
    queue.add(data);
    return false;
  }

  ...

  setInterval(processQueue, OFFLINE_QUEUE_TIMEOUT);

由于可怕的HACK ,这远非理想,还因为在我处理此队列时可能会捕获更多错误,因此它们将被乱序发送......

关于今天的最后一点:我认为你应该公开_sendProcessedPayload 。 当shouldSendCallback返回 false 时,它​​会在_send退出的地方启动,所以如果你想重试发送,它是调用的明显选择......

但是,我不喜欢它修改有效负载。 所以,这不是理想的方法。

此功能是否已添加到库中。

我今天遇到了这个需求,因为我有一个离线功能。 我使用 indexdb 存储我自己的所有数据,但是为 Sentry 提供开箱即用的离线功能会很好。 如果它可以使用它自己的本地数据库来存储事件并定期/在网络上更改尝试发送和清除数据库,那将是非常有用的。

如果我确实存储了异常以便在我上线时稍后发送,有没有办法让我在异常上设置时间戳,以表明当我将它们发送到哨兵时它们现在没有发生,但在某个时刻过去的? 我想我可以将它添加到额外内容中,但能够设置实际时间戳会很好。

我在captureException没有看到任何这样的选项

此页面是否有帮助?
0 / 5 - 0 等级