Posted at

javascriptでスタックトレース

More than 5 years have passed since last update.

javascriptでちょっと賢いロガーっぽいのを作ったとしても、最終的にはconsole.logを使ったりすると、ログの表示箇所が全て同じファイル、行になるのでいまいち不便。

そこで、V8エンジンのブラウザだけだけど、スタックトレースを取得してログメソッドが実行された行数、ファイル名などを一緒に出力する方法を調べた。

https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi

を使えばいける。例えばこんな感じ。

Error.prepareStackTrace = function( e, st ) {

return {
functionName: st[0].getFunctionName(),
lineNumber: st[0].getLineNumber(),
//いろいろお好きに
};
};

function log( msg ) {
var obj = {};
Error.captureStackTrace( obj, log );
console.log( msg + " at " + obj.stack.functionName /* 後はお好きに */ );
}

captureStackTraceを実行すると、スタックトレースが生成される。第2引数の"log"は、今まさに実行している関数を渡していて、これによってスタックトレース情報からcaptureStackTraceを呼んでいる自分自身の関数情報が除外される。

obj.stackにアクセスすると、初回アクセスであればスタックトレースがフォーマットされる。普通は文字列で生成されるのだけど、prepareStackTraceを上書きすると、任意のフォーマットで生成することができる。

prepareStackTraceのstには、実行行数、ファイル名などのトレース情報が配列で入っていて、それぞれgetFunctionNameなどを実行すると実行時の関数名などが取得できる。上の例では、必要な情報だけオブジェクトにして返している。

これうまく使えば、かなり詳細なログ情報を出せる。注意点として、prepareStackTraceに設定したフォーマッタは通常のエラー発生時のスタックトレースのフォーマットにも適用されるという点。元のフォーマッタを一度何かの変数に参照させておいて、用が済んだら元に戻すとかしたほうが良いかも。