フランス拠点のJavaアプリで、日次バッチが数件だけ失敗する現象があった。1日あたりの処理は約12万件、失敗は0〜3件。スタックトレースは Exception levée lors du traitement du lot のように現地語で出るが、原因の型名や行番号は英語のままなので、そこを検索キーにすれば追える。問題は複数行にまたがる例外が混ざり、grepで前後の文脈が切れることだった。
まず例外ブロックを1行に畳む。対象は logs/batch-*.log で、1ファイル数十MB程度。
for f in logs/batch-*.log; do
awk '/Exception|Erreur/{if(buf!="")print buf; buf=$0; next} /^\s+at /{buf=buf" "$0; next} {if(buf!=""){print buf; buf=""}} END{if(buf!="")print buf}' "$f"
done > /tmp/exceptions.txt
これで at com.example... の行が同じ行に残り、型名とフレームを一度にgrepできる。次に型名だけ抽出する。
grep -oE '[A-Za-z0-9_.]+(Exception|Error)' /tmp/exceptions.txt | sort | uniq -c | sort -nr | head -20
今回は NullPointerException が大半で、特定の入力ファイルに欠損行があるケースに収束した。現地語のメッセージ本文は読まなくても、型とフレームで十分絞れた。
この方法の利点は、ロケール設定を変えずに済むこと。アプリ側の LANG を触ると他拠点の表示に影響が出るため、ログはそのまま、検索側で構造を揃える方が副作用が小さい。代わりに、畳んだ時点で改行位置の情報は失われるので、原因箇所を特定した後は元ファイルに戻って前後を読む必要がある。
失效するのは、例外メッセージの中に改行を含む引用や、Caused by: が多段に続く場合。上のawkは最初の at 行以外を畳まないので、多段の因果関係は追い切れない。自分はこれで一度、根本原因を1段下の Caused by と取り違えた。多段が疑わしいときは畳まず、grep -n で行番号だけ拾って元ログを sed -n で範囲表示する方が確実だった。
フランス拠点のログで、現地語メッセージを英語キーに寄せる際、例外の多段構造をどう保持して検索していますか。
0 条评论
还没有评论,写下第一条。