可能由于网络、浏览器问题、缓存等原因,可能导致线上执行 js 的时候与开发环境并不一样,会抛出异常。js 异常基本上是前端开发工程师的家常便饭。如何记录,并使用它,却很少人关注。最近在考虑一个想法,基本上涉及到两步:收集和使用。 一、收集 对于 error 收集这一块,还是比较方便的,因为在各浏览器中都有一个接口: window.onerror = function(errorMessage, scriptURL, lineNumber) { alert(errorMessage, scriptURL, lineNumber) } 甚至中提供了 Stack Trace,比如在 try { fn() } catch(e) { alert(e.stack) } 所以收集这些错误还是比较方便的,这里需要注意的事,使用 二、使用 之前在支付宝的时候,线上 js 报错会变成一个邮件,发给前端开发 team,每个人自己认领、解决。其实这是一个不错的选择,也解决了最基本的问题:立即响应,修掉。不过也存在着一个问题,如果避免同样的错误?我的初步想法是这样的:
为什么这样做?主要是为了解决下面的一些问题:
三、注意点 1. 收集的时候使用 POST 发送 有时候 Error Message 可能会比较长,而浏览器的 URL 长度是有限制的,如果存的错误不多的话,可以考虑用 GET 发送,但通常来说 POST 可以把所有数据都发送到后台。 2. 何时发送数据 建议在触发 3. 存于数据库以哪个作为索引比较好? 通常来说以 URL 可能会比较适合多数网站。但像百姓网、淘宝等 UGC 比较多的网站,可能需要变通一下以记录 URL。毕竟不同帖子不同 URL 都是同一套代码。 那以 Error 作为索引呢?其实无论是那种,看自己需求选择吧。 4. 是否记录所有错误 这个也比较合适根据需求来看。百姓网有各种乱七八糟的报错可能都是来自到 baidu / Google 的 ad 外链。 四、结语 目前初步实现了一个收集的工具(sofish/stacktrace.js)和存储方式(以 URL 为索引),是否继续,还需要时间和进一步考虑,先发出来,抛砖引玉。 五、附录<?php $url = new Url(); $page = $url->post('page'); if(!$page) return; class ErrorTrace extends MongoData { // MongoData 中没有,区别 http://stackoverflow.com/a/7958954 public function findOne($obj) { return $this->connection->findOne($obj); } }; $store = new ErrorTrace(); $fields = array( 'url' => $url->post('url'), 'message' => $url->post('message'), 'line' => $url->post('line'), 'ua' => $url->post('ua'), ); $index = array('page' => $page); $hash = md5(json_encode($fields)); // 不重复记录一个错误,所有错误记录在同一个 URL 下 if($field = $store->findOne($index)) { if(isset($field[$hash])) return; return $store->setAttr(new Query('page', $page), $hash, $fields); } $store->page = $page; $store->$hash = $fields; $store->save(); ?> This Gist brought to you by GitHub. |