TT Lab
はじめる
学ぶ 学習パス コース

デバッグ実戦

トレースバックから計装まで

TT Labで続きを見る

目標

トレースバックから原因を3分で特定し、直して終わりにせず、次回のための計装まで埋め込めるようになります。

なぜ重要なのか

トレースバックは下から上へ読みます。最下行が例外の種類と理由を語り、そのすぐ上が実際に落ちたコード行で、上のほうはそこまで至った経路です。そして、例外メッセージにはたいてい問題を起こした実際の値が入っているので、その値で元データを検索すれば、数秒で犯人の行が見つかります。

もう1つ重要なのは、トレースバックが標準出力ではなく標準エラー出力に出るという事実です。顧客企業のバッチジョブのcron設定に2>&1が抜けていて、何か月も失敗の原因がどこにも残っていないケースが本当によくあります。「ログに何もない」と言われたら、まずこれを確認してください。

最後に、直して終わりにすると、来週同じことが繰り返されます。読み飛ばした行を記録するようにする1行が、次回の調査時間を30分から1分に縮めます。これが計装の埋め込みであり、再現しない問題を扱う正攻法でもあります。

ステップ

  1. /root/traceを作成し、/opt/app/report.pyを/root/trace/report.pyにコピーしてください。
  2. 失敗する実行の出力を、標準エラー出力まで含めて/root/trace/traceback.txtに保存してください。
  3. 発生した例外の名前だけを/root/trace/error_type.txtに書いてください。
  4. 実行を最初に止めた行のidの値を/root/trace/bad_row.txtに書いてください。
  5. /root/trace/report.pyを仕様どおりに直し、終了コード0で終わるようにしてください。
  6. 直したスクリプトの出力を/root/trace/out.txtに保存してください。rows=18 total=130400と出力されるはずです。
  7. 読み飛ばした行を、1行に1つずつ/root/trace/skipped.logに残すよう、計装を入れてください。
  8. 同じスクリプトを/opt/data/orders_api.csvに対して実行し、出力を/root/trace/out2.txtに保存してください。

参考

作業用コピーを作る

/root/traceを作成し、/opt/app/report.pyを/root/trace/report.pyにコピーしてください。

/root/traceを作成し、/opt/app/report.pyをその中にコピーしてください。

失敗の原文を確保する

失敗する実行の出力を、標準エラー出力まで含めて/root/trace/traceback.txtに保存してください。

トレースバックは標準出力ではなく標準エラー出力に出ます。リダイレクトに2>&1が必要です。

例外の種類を書く

発生した例外の名前だけを/root/trace/error_type.txtに書いてください。

トレースバックの最下行で、コロンの前の部分が例外の名前です。名前だけを書いてください。

最初に失敗した行を特定する

実行を最初に止めた行のidの値を/root/trace/bad_row.txtに書いてください。

例外メッセージに実際の値が入っています。元のCSVで、その値を持つ行のidを探してください。

終了コード0にする

/root/trace/report.pyを仕様どおりに直し、終了コード0で終わるようにしてください。

docstringの仕様に、有効な行の条件が3つ書かれています。条件に合わない行は読み飛ばして、処理を続ける必要があります。

集計結果を保存する

直したスクリプトの出力を/root/trace/out.txtに保存してください。rows=18 total=130400と出力されるはずです。

直したスクリプトの出力を、そのままファイルに渡してください。rows=とtotal=の2つの値が両方必要です。

読み飛ばした行を記録する

読み飛ばした行を、1行に1つずつ/root/trace/skipped.logに残すよう、計装を入れてください。

次回同じことが起きたときに1分で終わるよう、計装を埋め込むステップです。読み飛ばした行1つにつき1行ずつ残してください。

別の入力で実行してみる

同じスクリプトを/opt/data/orders_api.csvに対して実行し、出力を/root/trace/out2.txtに保存してください。

今日のデータにだけ合わせた修正は、修正ではありません。/opt/data/orders_api.csvで同じスクリプトを実行し、結果を保存してください。