2017-02-07 7 views
9

ここでは、Sequelize promise(Bluebird)のエラーを再起しています。最初は、これはエラーメッセージを変更するために行われましたが、現れたように、これはより有益なスタックトレースを生成します。再スローされたエラーでスタックトレースをマージする

それは

originalError.stackは、エラーの原因となった行が含まれていませんが、それはそれはSequelizeとMySQLドライバに起因することが重要な情報を保持している
sequelize.sync().catch(originalError => { 
    const rethrownError = new Error(originalError.msg + ': ' + originalError.sql); 
    throw rethrownError; 
}); 

のようなものです:

SequelizeDatabaseError: ER_KEY_COLUMN_DOES_NOT_EXITS: Key column 'NonExisting' doesn't exist in table 
    at Query.formatError (...\node_modules\sequelize\lib\dialects\mysql\query.js:175:14) 
    at Query._callback (...\node_modules\sequelize\lib\dialects\mysql\query.js:49:21) 
    at Query.Sequence.end (...\node_modules\mysql\lib\protocol\sequences\Sequence.js:85:24) 
    at Query.ErrorPacket (...\node_modules\mysql\lib\protocol\sequences\Query.js:94:8) 
    at Protocol._parsePacket (...\node_modules\mysql\lib\protocol\Protocol.js:280:23) 
    at Parser.write (...\node_modules\mysql\lib\protocol\Parser.js:74:12) 
    at Protocol.write (...\node_modules\mysql\lib\protocol\Protocol.js:39:16) 
    at Socket.<anonymous> (...\node_modules\mysql\lib\Connection.js:109:28) 
    at emitOne (events.js:96:13) 
    at Socket.emit (events.js:188:7) 
    at readableAddChunk (_stream_readable.js:176:18) 
    at Socket.Readable.push (_stream_readable.js:134:10) 
    at TCP.onread (net.js:548:20) 

rethrownError.stackは含まれてい関心のあるポイント(スタックの最初の行)が他のすべてはゴミです:

Error: ER_KEY_COLUMN_DOES_NOT_EXITS: Key column 'NonExisting' doesn't exist in table 
    at sequelize.sync.catch (...\app.js:59:17) 
    at tryCatcher (...\node_modules\bluebird\js\release\util.js:16:23) 
    at Promise._settlePromiseFromHandler (...\node_modules\bluebird\js\release\promise.js:504:31) 
    at Promise._settlePromise (...\node_modules\bluebird\js\release\promise.js:561:18) 
    at Promise._settlePromise0 (...\node_modules\bluebird\js\release\promise.js:606:10) 
    at Promise._settlePromises (...\node_modules\bluebird\js\release\promise.js:681:18) 
    at Async._drainQueue (...\node_modules\bluebird\js\release\async.js:138:16) 
    at Async._drainQueues (...\node_modules\bluebird\js\release\async.js:148:10) 
    at Immediate.Async.drainQueues (...\node_modules\bluebird\js\release\async.js:17:14) 
    at runCallback (timers.js:637:20) 
    at tryOnImmediate (timers.js:610:5) 
    at processImmediate [as _immediateCallback] (timers.js:582:5) 

2つの無関係のログエントリとして追加するだけでなく、両方の情報を保持し、それらの間のリンクを指定したいと考えています。

私は連結スタックを使用して単一のエラーとしてログに記録することを考えていました。rethrownError.stack += '\n' + originalError.stack

この2つのエラーはどのように処理する必要がありますか?彼らのスタックトレースは結合されるべきですか? JavaScript(特にNode.js)でエラースタックをマージする方法はありますか?

結果のエラーを意味のあるものにし、エラースタックトレース(つまりStacktrace.js)を解析する既存のツールを動揺させないようにすることを意図しています。

プロジェクトではWinston loggerまたはプレーンconsole.errorを使用しているため、エラーが文字化けしています(上の例では、未処理の拒否ハンドラを介して記録されています)。

+0

をsequelize公平なビットを使用誰かのよう:なぜあなたはすべてで再スローされますか?'catch()'を押した瞬間、それ以上のスローにならないようにエラーを処理する必要があります。 –

+0

@ Mike'Pomax'Kamermansそれは疑問の範囲外ですが、元々は 'sql'のエラーを' msg'に連動させるためにこれを行いました。私は非常にうれしくはありませんでしたER_KEY_COLUMN_DOES_NOT_EXITSは説明しません何でもしかしここでは、再スローされたエラーからのスタックに興味があります、 'sequelize.sync.catch ...'で。元のエラーから、どこに発生したのかは明らかではありません。 – estus

+0

[XY問題](http://meta.stackexchange.com/a/66378)を回避することを防ぐウサギの穴は決して範囲外です。あなたのコメントからのエラーについては、それは*その列名を持たないテーブルの列名を使用していることを伝える非常に明確なMySQLエラーです。そこにエラーを再現するだけの価値はありません。使用しようとしたテーブル名とユーザのカラムセットをログに記録して、MySQLの 'show create table {tablename}' –

答えて

5

はVERRORに軽量な代替手段です:rerror (私は著者です)

考え方は同じです。エラーの折り返しエラー。しかし、はるかに簡単です。機能は少なくて済みますが、ブラウザでも機能します。また、スタックトレースの作成にはコストがかかります。スタックトレースを作成して文字列に追加する代わりに、内部的にエラーのスタックを作成し、必要な場合にのみ大きなスタックトレースを作成します(ゲッターを使用します)。

function fail() { 
    throw new RError({ 
    name: 'BAR', 
    message: 'I messed up.' 
    }) 
} 

function failFurther() { 
    try { 
    fail() 
    } catch (err) { 
    throw new RError({ 
     name: 'FOO', 
     message: 'Something went wrong.', 
     cause: err 
    }) 
    } 
} 

try { 
    failFurther() 
} catch (err) { 
    console.error(err.why) 
    console.error(err.stacks) 
} 

出力

FOO: Something went wrong. <- BAR: I messed up. 
Error 
    at failFurther (/Users/boris/Workspace/playground/es5/index.js:98:11) 
    at Object.<anonymous> (/Users/boris/Workspace/playground/es5/index.js:107:3) 
    at Module._compile (module.js:556:32) 
    at Object.Module._extensions..js (module.js:565:10) 
    at Module.load (module.js:473:32) 
    at tryModuleLoad (module.js:432:12) 
    at Function.Module._load (module.js:424:3) 
    at Module.runMain (module.js:590:10) 
    at run (bootstrap_node.js:394:7) 
<- Error 
    at fail (/Users/boris/Workspace/playground/es5/index.js:88:9) 
    at failFurther (/Users/boris/Workspace/playground/es5/index.js:96:5) 
    at Object.<anonymous> (/Users/boris/Workspace/playground/es5/index.js:107:3) 
    at Module._compile (module.js:556:32) 
    at Object.Module._extensions..js (module.js:565:10) 
    at Module.load (module.js:473:32) 
    at tryModuleLoad (module.js:432:12) 
    at Function.Module._load (module.js:424:3) 
    at Module.runMain (module.js:590:10) 

Aを読み取る推奨:https://www.joyent.com/node-js/production/design/errors

+0

私はそれを評価します。確かに良い読書、ありがとう。 – estus

3

私が知る限り、Node.jsにネストされたエラーを処理する組み込みの方法はありません。私がお勧めできるのはVError libraryです。これは、高度なエラー処理を扱うときには本当に便利です。

あなたは多くのエラーのスタックトレースを組み合わせることfullStackを使用することができます。ここでは

var err1 = new VError('something bad happened'); 
var err2 = new VError(err1, 'something really bad happened here'); 

console.log(VError.fullStack(err2)); 
+0

に対して確認できます。このパッケージについて知りませんでしたが、明らかにこのコンテキストでは面白そうです。この状況にそれを適用する方がどうしたらよいかまだ分かりません。私は 'MultiError'を使用しようとしましたが、' first of 2 errors ... 'を出力します。これは素晴らしいですが、エラーが記録されてもスタックトレースは失われます。 – estus

+0

私は 'fullStack'メソッドの詳細について私の回答を編集しました。 –

+0

ありがとう、それは助けた。 – estus

関連する問題