让我们从一个故事开始。一个用户故事
我的一个朋友在中午给我打电话,提出一个非常奇怪的要求。他告诉我
“你能过来帮我填写一张表格吗?”
我很惊讶,因为填写表格是在线最容易的事情,不是吗?即使对于不太精通技术的人来说也是如此。
所以我去了我朋友家,结果却发现没那么简单!我花了 25 分钟调试这个网站(一个保加利亚的政府网站)出了什么问题。问题是缺少验证(通过 XMLHttpRequest)。
当然,我给代理机构打电话,以为一切都会进入 /dev/null/
,但令人惊讶的是,他们对这个问题很感兴趣,所以我又花了 25 分钟解释问题,并将他们需要的所有数据发送给他们。这些包括
- 屏幕尺寸
- 浏览器和操作系统版本
- 问题究竟发生在哪里
- Javascript 错误和 XHR 日志(粘贴在电子邮件中)
- 我朋友浏览器上安装的插件
等等,等等,等等...... 你知道我在说什么。
真是太累了。
完美的错误报告
让我们先把故事放在一边,更多地从开发人员的角度考虑问题。开发人员需要什么才能快速解决问题,而无需询问用户困难的问题
- 屏幕尺寸、插件、安装在您的浏览器上、问题发生的 URL、操作系统和浏览器版本
- 一个带有注释的视觉截图,显示问题的确切位置以及它在用户眼中看起来的样子,以及所有关于如何重现错误的步骤。
对吧?
等等,好像少了点东西。
大多数来自用户的错误报告最糟糕的一点是,它们发生在客户端,在前端 javascript 中,一个残酷、残酷的地方,远离试图修复它们的开发人员。
同意?这就是为什么完美的错误报告应该包含其他内容——一个可浏览的 JavaScript 错误和 XHR 日志记录器.
看看
谈谈代码:记录的 JavaScript 错误
该 Usersnap 控制台记录器 保存所有类型的 JavaScript 错误。您可以在 Usersnap 仪表板中浏览 Web 开发人员控制台,就好像您坐在用户的浏览器上一样!
每个错误/日志都包含一个 NTP 同步时间戳,一个完整的堆栈,包括 JavaScript 源文件、行号和格式,就像您在Firebug中已经知道的开发人员控制台一样。
由 console.log
、console.info
、console.warn
或 console.error
发出的每个调试日志都会被正确格式化(包括递归对象/数组格式化和浏览)。
保证在调试期间不会出现 [object Object]
地狱!
访问未定义/空对象的属性
第一个例子在现实中经常发生:一个固定元素应该通过在滚动时使用 top
属性来对齐另一个元素。
然而,由于标记重做,元素 #inexistent
不再存在。这导致 offset()
返回 null
,而属性 top
就无法访问了。
function clicky() {
console.info("Accessing a property of an undefined object");
console.log("calculating scroll top %d", $('#inexistent').offset().top);
};
调用未定义对象的函数
这里还有另一个重做案例:有人试图在一个未定义的对象上调用一个函数。
function clicky2() {
console.info("Calling a method of an undefined object");
adjust.ScrollBottom();
};
普通异常
有时你甚至在开发过程中就知道某些东西可能会坏——如果能知道它在什么时候坏掉不是很好吗?
function clicky3() {
console.info("Throwing an exception");
throw "Version Mismatch!";
};
XHR 错误
有时,XHR 会传回错误(如 404 未找到
或 500 内部服务器错误
)。大多数情况下,此类错误会导致很难重现的错误。
function clicky4() {
console.info("404 on XHR");
$.ajax({
"url": "non_existing.php"
});
};
跨域 XHR 很麻烦。想象一下,有人更改了 CORS 标头,而您的跨域 XHR 从一天到第二天就不再起作用了。
function clicky5() {
console.info("Cross-Origin on XHR");
$.ajax({
"url": "http://facebook.com/cross-origin"
});
};
XHR 和时间跟踪
记录结账过程中的步骤
转换率是大多数企业的关键。用户遇到的任何障碍都会降低您的转化率——例如,加载页面需要太长时间,或者在结账时甚至出现了错误。
这个简短的示例展示了一个标准的点击处理程序,它通过 XHR 调用 getcheckout.php
。不幸的是,第二个 XHR (confirm.php
) 失败并抛出 JavaScript 异常。这很好,但是:用户没有收到任何反馈。页面只是停滞了。
function checkout() {
console.log("check out clicked!");
$.ajax({
url: "getcheckout.php",
dataType: "json"
}).done(function(data) {
console.log("Checked out: %o", data);
confirm();
});
};
function confirm() {
confirmService.checkConfirm();
$.ajax({
url: "confirm.php"
}).error(function() {
throw "internal server error on confirm!";
});
};
此外,您将获得用户操作的完整同步时间框架(无论用户浏览器上的时间是否正确!)。对象 (console.log(“Checked out: %o”, data);
) 的完整格式支持非常便于调试。
结论
现在,每个开发人员都可以拥有理解问题究竟在哪里发生的超级能力,即使是在客户端,也可以停止担心“它不起作用。尽快修复!”类型的沟通。
现在,每个用户都可以更好地报告问题,因为他们只需要 按一下按钮来报告问题,使用他们熟悉的工具,魔法就会在后台发生。
FOSS 项目的免费许可证
我们在 Usersnap 支持并相信 FOSS(自由/自由和开源)运动,这就是为什么 Usersnap 对任何 FOSS 项目使用都是免费的(就像免费啤酒一样)。
我们利用了许多开源组件,例如 nginx、python、rabbitmq、angular,回馈社区并提高项目质量是说“谢谢”的一种方式。
您的项目必须满足以下所有条件才能获得批准
- 该项目已获得 开放源代码计划批准的 许可证。
- 项目源代码可供下载。
- 您的开源项目有一个公开可访问的网站。
关于 Bogomil Shopov
Bogo 是 Mozilla 长期的贡献者。目前帮助 Web 项目团队在 Usersnap 上变得很棒。蒙提·派森迷。
更多由 Bogomil Shopov 撰写的文章......
关于 Robert Nyman [荣誉编辑]
Mozilla Hacks 的技术布道者和编辑。发表有关 HTML5、JavaScript 和开放网络的演讲和博客文章。Robert 是 HTML5 和开放网络的坚定支持者,自 1999 年以来一直在从事 Web 前端开发工作——在瑞典和纽约市。他还定期在 http://robertnyman.com 上撰写博客文章,喜欢旅行和结识新朋友。
4 条评论