Node.jsでカレント実行行を取得する

Node.jsでエラー発生時に適当に console.log とかを埋めて、しかもそれが複数箇所になってくると、エラーメッセージは分かるがそれがどこで発生したエラーなのかが分からなくて困ったりする。キャッチしたエラーオブジェクトが普通にthrowされたErrorオブジェクトならerr.stackでコールスタックが取得できるからまだしも、只の文字列や独自Errorをcallback(new Error("オレオレメッセージ"))とかで渡されるとコールスタックが取れないのでどうしようとした足跡。

試行錯誤

で、以下の様な関数を作ってみた。仕組みは簡単で、throwしないと行番号取得できないならダミーで例外発生させちゃえば良いじゃないって感じ。*1

function getCallStack() {
  try {
    throw new Error("DUMMY");
  } catch(e) {
    return e.stack.split(/[\r\n]+/).filter(function(v,v2,v3){
      return /^    at .*:[0-9]+:[0-9]+/.test(v);
    });
  }
}


試しに適当な箇所で console.log(getCallStack()) すると以下の様にコールスタック情報を配列で取得できるようになる。

[ '    at getCallStack (/home/kawaz/workspace/test/app.js:866:11)',
  '    at /home/kawaz/workspace/test/app.js:853:19',
  '    at Object. (/home/kawaz/workspace/test/app.js:440:15)',
  '    at param (/home/kawaz/.nvm/v0.4.6/lib/node/.npm/connect/1.3.0/package/lib/middleware/router.js:148:21)',
  '    at param (/home/kawaz/.nvm/v0.4.6/lib/node/.npm/connect/1.3.0/package/lib/middleware/router.js:159:15)',
  '    at pass (/home/kawaz/.nvm/v0.4.6/lib/node/.npm/connect/1.3.0/package/lib/middleware/router.js:164:10)',
  '    at /home/kawaz/.nvm/v0.4.6/lib/node/.npm/connect/1.3.0/package/lib/middleware/router.js:154:19',
  '    at /home/kawaz/workspace/test/app.js:571:9',
  '    at [object Object]. (/home/kawaz/.nvm/v0.4.6/lib/node/.npm/mongodb/0.9.2/package/lib/mongodb/collection.js:448:35)',
  '    at [object Object].emit (events.js:67:17)' ]


なので、今まで console.log(err) とかしてた代わりに、console.log(err, getCallStack()[1]) としておけばconsole.log()を実行した行番号付きで以下のように出力されるようになる。

オレオレメッセージ    at /home/kawaz/workspace/test/app.js:853:19

ちゃんとしたアプリにしようと思ったら微妙かもだけど、ちゃちゃっとコード書くときには便利なTipsだと思います。

追記) 文字列処理なしで取れました!

結論、Error.prepareStackTraceを使えば解決する。
あと関係ないけど、はてなのツイッター記法を初めて知った。一連のツイートを貼り付ける時とかに便利だなコレ。

*1:この関数ではとりあえず文字列の配列を返すけど、行番号と列番号は簡単にパースできるので省略。