JavaScriptのエラーを検知したり、スタックトレースをいいかんじに表示する術

こんにちは。タブの開きすぎで、タブが増やせなくなりました、きたけーです。

JavaScriptのエラー検知

アプリケーション全体のエラーを検知するには、windowオブジェクトにonerrorハンドラを設定します。こんなかんじ。

window.onerror = function (message, file, line, col, error) {
  return true;
};

ハンドラの引数にエラーメッセージ、発生したファイル名、行数、列数、エラーオブジェクトが渡ります。col と error は、一部のブラウザ(ChromeとかOpera)しか渡らないので注意。

スタックトレースの表示

エラーオブジェクトのスタックはerror.stackで取得できますが、stacktrace.jsをつかうとスタックトレースをいいかんじで表示できます。

こんなかんじ (stacktrace.jsの導入にはbowerをつかってます)

<script src="./bower_components/stacktrace-js/stacktrace.js"></script>
<script>
window.onerror = function (message, file, line, col, error) {
  var trace = printStackTrace({e: error});
  alert(trace.join('\n\n'));
  return true;
};

function foo() {
  unExis(); // ここでエラーになる
};

function bar() {
  foo();
};

bar();
</script>

alertで表示した結果。

f:id:kitak:20141008091047p:plain

stacktrace.jsですが、そのうち使い方が変わるので注意が必要です。(refs: misnamed function printStackTrace() · Issue #68 · stacktracejs/stacktrace.js · GitHub) issueが閉じられたのが、この記事を書いている1時間前。とほほ。

所感とか疑問

大手Webサービスがクライアント側で発生したJavaScriptのエラーをどう収集しているのか まとめ - Qiita をみると、onerrorでエラーを検知する場合は、(対応しているブラウザがまちまちなので)確実に送信できる内容がエラーメッセージ、行番号、URL(ファイル名)に限定されるのが分かる。 はてなブログの場合だと、アプリケーション全体ではなく、Ajaxの通信であったり、関数の実行のレベルで例外をつかまえているようなので、エラーオブジェクトからスタックトレースを送信できる。

ここで疑問なのがNewRelicのBrowser > JS errorsで、ダッシュボードを見る限り、アプリケーション全体で、かつブラウザを限定せずにスタックトレースが取れているのが分かる。 Announcing JS Error Reporting and AJAX Timing - New Relic blog には、「window.onerrorただつかってるわけじゃないよ」って書いてあったのだけど、どうやって実現しているのかなぁ... JS stacktraces. The good, the bad, and the ugly. - Bugsnag に書いてあるみたいに機能検出して、関数をラップしたりしているのかな。