我们如何跟踪 Javascript 错误?现有的工具真的有效吗?

Posted

技术标签:

【中文标题】我们如何跟踪 Javascript 错误?现有的工具真的有效吗?【英文标题】:How do we track Javascript errors? Do the existing tools actually work? 【发布时间】:2014-01-15 14:17:34 【问题描述】:

今天我发现需要跟踪和检索 javascript 错误堆栈跟踪来解决它们。

今天我们能够捕获所有的 rest 调用,其想法是,一旦您遇到错误,自动发布该错误的堆栈跟踪以及其余已保存服务的响应,以便我们可以检测、重现和解决问题几乎相同的环境/情况。

作为一项要求,我们被要求制作一个可以包含而不会造成干扰的模块,例如: 在一个 JS 中包含包含 hook 逻辑的模块,不会侵入,在各种 JS 文件中包含几行代码会侵入。

目标是制作一个可以包含在已开发系统中并跟踪错误事件(如控制台)的工具。

我已经阅读了有关此跟踪器逻辑的信息:

errorception.com/ trackjs.com/ atatus.com/ airbrake.io/ jslogger.com/ getsentry.com/ muscula.com/ debuggify.net/ raygun.io/home

我们需要做类似的事情,跟踪错误并将其发送到我们的服务器。

正如“Dagg Nabbit”所说... “很难从现在“在野外”发生的错误中获取堆栈跟踪”...

所以,我们有很多付费产品,但它们是如何真正发挥作用的呢?

在 Airbrake 中,他们使用 stacktrace 和 window.onerror:

window.onerror = function(message, file, line) 
  setTimeout(function() 
    Hoptoad.notify(
      message : message,
      stack   : '()@' + file + ':' + line
    );
  , 100);
  return true;
;

但我无法弄清楚堆栈跟踪何时真正使用。

在某些时候,stacktrace、raven.js 和其他跟踪器需要 try/catch。

    如果我们找到一种方法来制作全局包装器会怎样? 我们可以调用 stacktrace 并等待捕获吗?

当客户端发生意外错误时,如何将堆栈跟踪发送到我的服务器?有什么建议或好的做法吗?

【问题讨论】:

我知道appenlight.com 有一个免费帐户,但有一些限制。但是对于开源项目,它是免费的。我一直关闭这个问题,因为它是为了搜索产品,但我觉得我仍然可以提供一些替代方案,直到它可能被删除 ***.com/q/5328154/139010的可能重复 @LoïcFaure-Lacroix,它不再搜索产品,我更改了它。你提到的产品是否真的发送了堆栈跟踪,或者只是错误消息和它发生的位置? @Da3 您可以创建一个脚本加载器函数并使用它来代替以通常方式加载脚本。它可以用 XHR 抓取脚本,在它们周围添加try ... catch,然后评估它们或将它们粘贴到脚本标签中。它会产生一大堆其他问题,例如遇到同源策略并使堆栈跟踪中的文件名无用。另一种选择可能是设置执行相同操作的服务器端脚本加载器代理;这可能会很好。 @Da3 在你的服务器上设置一些东西来处理像domain/jsproxy/scheme/url 这样的 URL,例如yourserver.com/jsproxy/http/code.jquery.com/jquery.js。您可以像 php example 那样抓取文件并提供它,或者您可以将内容缓存在磁盘或内存中并检查远程资源是否有更改,而不是每次都获取它们。 【参考方案1】:

现在很难从“野外”发生的错误中获取堆栈跟踪,因为 window.onerror 无法使用 Error 对象。

window.onerror = function(message, file, line)  

还有一个new error event,但是这个事件还没有暴露错误对象。

window.addEventListener('error', function(errorEvent)  )

很快,window.onerror 将获得一个包含 Error 对象的 fifth parameter,您可能可以使用 stacktrace.js 在 window.onerror 期间获取堆栈跟踪。

<script src="stacktrace.js"></script>
<script>
window.onerror = function(message, file, line, column, error) 
    try 
        var trace = printStackTrace(e: error).join('\n');
        var url = 'http://yourserver.com/?jserror=' + encodeURIComponent(trace);
        var p = new printStackTrace.implementation();
        var xhr = p.createXMLHTTPObject();

        xhr.open('GET', url, true);
        xhr.send(null);
     catch (e)  

</script>

在某些时候,错误 API 可能会被标准化,但目前,每个实现都不同,因此使用类似 stacktracejs 之类的东西来获取堆栈跟踪可能是明智的,因为这样做需要每个浏览器都有单独的代码路径。

【讨论】:

window.onerror 错误对象仅在 Chrome 上可用。 AFAIK 没有其他浏览器承诺过。 @ToddGardner 好点。我期待他们最终会效仿onerror 现在是多么无用,但你永远不知道。 我相信 Mozilla 会,可能是 IE12 或其他东西。但不幸的是,我们将不得不处理一段时间内还没有这样做的旧浏览器:( 引用此内容的更新 - window.onerror 现在在大多数或所有主要浏览器的最新版本中都会收到错误消息。【参考方案2】:

我是上面提到的 TrackJS 的联合创始人。你是对的,有时获取堆栈跟踪需要一些工作。在某种程度上,异步函数必须包装在 try/catch 块中——但我们会自动执行此操作!

在 TrackJS 2.0+ 中,您传递给回调的任何函数(addEventListenersetTimeout 等)都将自动包装在 try/catch 中。我们发现我们几乎可以用它捕获所有东西。

对于我们现在可能会做的几件事,您可以随时尝试/抓住它。我们提供了一些有用的包装器来提供帮助,例如:

function foo() 
  // does stuff that might blow up


trackJs.watch(foo);

【讨论】:

“在 TrackJS 2.0+ 中,您传递给回调的任何函数(addEventListener、setTimeout 等)都将自动包装在 try/catch [..] 中”这对性能有什么影响? @Gajus 只是包装函数的开销,如:function foo() ... function bar() return foo();增量成本是调用bar() 而不是foo()【参考方案3】:

在最新的浏览器中,window.onerror 中有一个错误对象的第 5 个参数。 在addEventListener,可以通过event.error获取错误对象

// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) 
    console.log(message, "from", error.stack);
    // You can send data to your server
    // sendData(data);
;
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (event) 
    console.log(e.error.message, "from", event.error.stack);
    // You can send data to your server
    // sendData(data);
)

您可以使用图像标签发送数据,如下所示

function sendData(data) 
    var img = newImage(),
        src = http://yourserver.com/jserror + '&data=' + encodeURIComponent(JSON.stringify(data));

    img.crossOrigin = 'anonymous';
    img.onload = function success() 
        console.log('success', data);
    ;
    img.onerror = img.onabort = function failure() 
        console.error('failure', data);
    ;
    img.src = src;

如果您正在寻找开源,那么您可以查看TraceKit。 TraceKit 会挤出尽可能多的有用信息并将其标准化。您可以为错误报告注册订阅者:

TraceKit.report.subscribe(function yourLogger(errorReport) 
    // sendData(data);
);

但是,您必须做后端来收集数据和前端来可视化数据。

免责声明:我是 https://www.atatus.com/ 的一名网络开发人员,您可以在其中跟踪所有 JavaScript 错误并过滤各种维度(例如浏览器、用户、网址、标签等)的错误。

【讨论】:

【参考方案4】:

@Da3 你询问了appenlight 和堆栈跟踪。是的,只要您将异常包装在 try/catch 块中,它就可以收集完整的堆栈跟踪。否则它将尝试从非常有限的 window.onerror 读取信息。这是一个浏览器限制(将来可能会修复)。

【讨论】:

以上是关于我们如何跟踪 Javascript 错误?现有的工具真的有效吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何在现有的 django 网站上开始使用 react

如何在 angularjs 控制器中包含现有的 javascript 列表

如何将 Swagger UI 添加到现有的 GXT 或 GWT 项目并使用当前的 GWT-RPC REST 请求?

如何告诉 UIGestureRecognizer 取消现有的触摸?

如何从现有的 JavaScript 库生成 .d.ts “类型”定义文件?

如何使用 jQuery 将 JavaScript 代码添加到现有的 iFrame 中?