ログ調査は属人化する — 引き継げるチームの4つの工夫

技術解説

申し送りは3行だった。

昨日あなたが組んだ検索条件を、いま他人が再現できますか。

再現できない理由は記憶力ではなく、渡せる形をしていないことにあります。

ログ調査の成果は、たいてい「分かったこと」の形でしか共有されません。そこに至るまでの検索条件、除外した仮説、すでに見た範囲、色を付けた語——調査の状態にあたるものは、担当者が席を立った瞬間に消えます。今回はその4場面——シフト交代、数日がかりの調査、見ながらのメモ、そして画面共有——を、それぞれ「何が失われるのか」から順に見ます。

先に結論: UwView Pro なら検索条件とセッションを保存でき、翌日の自分にも交代した相手にも「同じ状態」を渡せます。行番号は多段階で絞り込んでも原本の座標のまま最後の段まで残るので、報告書にも口頭の指示にも「何行目」で書けます。一度開いたファイルは2回目以降、行番号付きのまま開き直せます(47.73GBのテキストで実測0.02〜0.07秒。特定環境での測定例で、環境により異なります。詳細は記事末尾)

本記事はログの調査手順をチーム内で共有する話です。ログの持ち出し範囲・共有可否・マスキング要否は、所属組織および委託元の規程に従ってください。


1. 申し送りに書けなかったもの

状況

障害が長引きます。夕方、シフトが交代します。

引き継ぎメモにはこう書きました。

14時台に5xxが集中。app.log を ERROR で検索して timeout を確認済み。
DB側のログは未確認。継続調査お願いします。

3行です。書いた本人は正確なつもりです。

そして受け取った人は、ほぼ最初からやり直します

なぜ起きるか

引き継げるのは結論だけで、調査の状態は文書化できる形をしていないからです。

「ERROR で検索した」は、実際には次のような経緯の最終形です。

  • 最初は ERROR で引いて件数が多すぎたので、時刻で絞った
  • timeout を足したが、これはヘルスチェックのものが混ざるので除外した
  • 除外した結果で残ったものにだけ、心当たりのある語を当てた

このうち申し送りに書けたのは1行目だけです。2行目の「除外した」が落ちると、受け取った人は同じ落とし穴に落ちます。しかも落ちたことに気づくまでに時間がかかります。

さらに、文字にならないものが3つ残ります。

  • 色分け — どの語にどの色を付けていたか。これは調査中に育つ暗黙知で、メモに書き写す習慣がありません
  • 見た範囲 — 「この時間帯はもう見た」という判断。ブックマークに相当するものですが、置き場所がありません
  • 行番号 — 「41,284,471行目あたりが怪しい」は、切り出したファイルを渡した時点で座標を失います(第16回で扱いました)

汎用ツールでの対処と限界

コマンドの履歴を残すのが、いちばん手軽な対処です。

# 調査に使ったコマンドだけを申し送りに残す
history | grep -E 'grep|awk|sed|zcat' | tail -30 > handover-$(date +%F).txt

# 条件そのものをファイルにして渡す
cat > patterns.txt <<'EOF'
5[0-9][0-9] 
OutOfMemoryError
connection refused
EOF
grep -nE -f patterns.txt app.log | head -50

パターンファイルは効きます。条件が成果物になるので、次の人が同じものを当て直せます。

限界は3つ。

ひとつめ、history には打ったものしか残らないこと。却下した仮説も、見て「問題なし」と判断した範囲も、コマンドを打たずに目で見た部分も残りません。残るのは試行の記録であって、判断の記録ではありません

ふたつめ、grep -f はORでしかないこと。パターンファイルに5行書けば、5つのいずれかに当たる行が出ます。しかし実際の調査は「Aで絞ってからBを除いてCを探す」という順序を持っています。順序=思考の形が、ファイルにすると平らになります。

みっつめ、出力を渡すと原本の座標が消えること。grep -n を付ければ行番号は残りますが、受け取った人がその行の前後を広げたければ、結局原本を開き直します。そして原本は数十GBです。


2. 「昨日の続きから」がない

状況

原因が分からず、調査が3日目に入ります。

朝、昨日と同じファイルを開きます。開くのに数分かかります。昨日たどり着いた場所へ戻るために、検索条件を組み直します。

昼前に、ようやく昨日の夕方の位置に戻ります。

なぜ起きるか

調査の状態が、アプリの外にしか置けないからです。

多くのツールは「起動 → 読み込み → 検索」を毎回ゼロから行います。終了時に持っていた状態——開いていた位置、絞り込みの段、色分け、比較のために並べていた2つ目のファイル——は、閉じた瞬間になくなります。

そして数日がかりの調査では、これが3つの形で効いてきます。

  • 条件が毎日わずかに変わる — 昨日は timeout を除外していたのに、今日は除外し忘れます。件数が変わったとき、それが条件の違いなのかデータの違いなのかが分かりません
  • ログが増えている — 調査中も本番は動いています。同じ条件でも件数が増え、どれが昨日見たもので、どれが新しいのかが区別できません
  • 待ちが積み上がる — 1日3分の読み込みでも、3日で9分。実際にはそれ以上に、「開き直すのが高いから、思いついた検索を後回しにする」という判断が入ります(第10回

汎用ツールでの対処と限界

「どこまで見たか」を外に書き出すのが基本です。

# 昨日の終わりにファイルサイズを記録しておく
wc -c < app.log > .checkpoint-$(date +%F)

# 翌朝、その続きだけを見る
tail -c +$(cat .checkpoint-2026-09-15) app.log | grep -n 'ERROR'

# 条件はスクリプトに固定する
cat > recheck.sh <<'EOF'
#!/bin/sh
grep -nE '5[0-9][0-9] ' "$1" | grep -v 'healthz' | tail -40
EOF
chmod +x recheck.sh

チェックポイントは安くて効きます。「新しく増えたぶんだけ」を見られると、差分に集中できます。

限界は2つ。

ひとつめ、バイトオフセットはローテーションで無意味になること。夜間に logrotate が走れば、翌朝の app.log は別のファイルです。記録した数字は、新しいファイルの意味のない位置を指します。inode を見て判定する手もありますが、そこまでやるなら仕組みとして用意されているべきものです。

ふたつめ、tail -c +N | grep -n の行番号が原本の座標ではないこと。出てくるのは「切り出した範囲の中での何行目か」です。昨日のメモに書いた「41,284,471行目」と、今朝の出力の「1,203行目」は、足し算でしか繋がりません。日をまたぐと、この足し算の基準そのものが記憶から抜けます。


3. 見ながらメモを取れない

状況

原因が分かりました。報告書を書きます。

ログのウィンドウと、ドキュメントのウィンドウを行き来します。該当行をコピーし、貼り付け、行番号を手で打ち込みます。前後の文脈も要るので、もう一度ログへ戻ります。

書き終えたころには、どの行番号がどの引用に対応していたか、自信がなくなっています。

なぜ起きるか

「読む側」と「書く側」が別のアプリで、両者をつないでいるのが人間の短期記憶だからです。

この接続部分で、決まったものが落ちます。

  • コピーすると行番号が落ちる — 選択してコピーするのは本文だけです。行番号は画面の左端にあって、選択範囲に入りません
  • スクリーンショットは後から使えない — 行番号ごと写せますが、検索できず、引用として再利用できず、画面の外にあった機微情報が写り込む事故も起きます
  • 文脈の量が決められない — 1行だけ貼ると意味が通らず、前後20行を貼ると報告書が読めなくなります。適量は読んでから決まるのに、貼るときにはもう元の画面を閉じています
  • 抽出ファイルを作ると出所が消える — 断片を作って貼れば楽ですが、その断片が原本のどこから来たのかは、断片自身には書かれていません

汎用ツールでの対処と限界

行番号を落とさない形で抜くのが要点です。

# 行番号つき・前後5行つきで抜いて、そのまま追記していく
grep -n -C 5 'OutOfMemoryError' app.log | tee -a findings.md

# 見つけた場所の行番号だけを台帳にしておく
grep -n 'OutOfMemoryError' app.log | cut -d: -f1 > hits.txt

# 台帳から、あとで文脈を再生成する
while read -r n; do
  sed -n "$((n-5)),$((n+5))p;$((n+6))q" app.log
  echo '---'
done < hits.txt

行番号の台帳が効きます。座標さえ残っていれば、文脈の量はあとから決め直せます。

限界は3つ。

ひとつめ、grep -n -C の出力が読みにくいこと。ヒット行は 41284471:、文脈行は 41284466- と区切り文字が変わり、ヒットの塊のあいだには -- が入ります。そのまま報告書に貼ると、この記号の説明から始めることになります。

ふたつめ、台帳からの再生成が毎回全走査になること。上のループは hits.txt の行数ぶん sed を回します。ヒットが40件あれば、数十GBのファイルを40回頭から数え直します(第15回)。

みっつめ、貼り込んだ断片を後から検証できないこと。レビューで「この引用、本当に原本にありますか」と聞かれたとき、確かめる唯一の方法は原本を開き直して同じ場所を見ることです。報告書を書く工程と、報告書を検証する工程が、どちらも同じ待ち時間を払います。


4. 画面共有でログを追う

状況

リモートで調査します。自分の画面を共有し、二人で追います。

「そこ、もう少し上」「あ、行き過ぎました」「その connection の行、拡大できますか」

スクロールは相手の回線越しに1秒遅れて届きます。30分話して、進んだのは1画面ぶんです。

なぜ起きるか

画面共有が共有しているのは映像であって、位置ではないからです。

この差は、そのまま4つの不便になります。

  • 相手は探せない — 見たい場所があっても、口で言って動かしてもらうしかありません。相手の頭の中にある仮説は、こちらの手を経由しないと検証できません
  • 文字が潰れる — 圧縮された映像では小さい等幅文字が崩れます。l1、全角スペースと半角スペース——この連載で何度も「1文字の違い」が原因だったという話をしてきましたが、その1文字が映像では読めません
  • 操作が塞がる — 相手が読んでいるあいだ、こちらはスクロールできません。二人で1つのカーソルを共有している状態です
  • ファイルを送れない — 相手が自分で開ければ解決しますが、数十GBは送れず、機微情報が入っていれば送ってはいけません

汎用ツールでの対処と限界

映像の代わりに座標を送ります。

# 位置を数字にして、チャットに貼る
grep -n 'transaction_id=8f21' app.log | head -3
#=> 41284471:2026-09-16T14:02:11 [worker-7] transaction_id=8f21 ...

# 相手は同じ番号を自分の手元で開く
sed -n '41284451,41284491p;41284492q' app.log

# どうしても断片を渡すなら、マスクしてから
sed -n '41284451,41284491p;41284492q' app.log \
  | sed -E 's/([0-9]{4})[0-9]{8}/\1********/g' > share.txt

いちばん安いのは行番号を言うことです。「41,284,471行目を見てください」は1行のチャットで済み、相手はそこから自分の意思で動けます。

限界は3つ。

ひとつめ、相手が同じファイルを持っている前提であること。持っていなければ座標は通じません。そして「持っている」ためには、相手の手元で開けるサイズである必要があります。

ふたつめ、sed -n は毎回先頭から数えること。二人が別々に、同じファイルを何度も頭から数え直します。会話のテンポで座標を出し合うには、1回あたりが重すぎます。

みっつめ、マスクのかけ忘れが事故になること。断片を渡す運用は、渡すたびに人間が判断します。急いでいるときほど飛ばされ、急いでいるときにしか起きない事故になります。


4つに共通していたもの

場面 失われるもの 詰まる原因 汎用ツールでの対処 残る問題
シフト交代 検索条件・色分け・見た範囲 文書化できるのは結論だけ history/パターンファイル 順序と却下した仮説が残らない
数日がかりの調査 昨日の状態 ツールが毎回ゼロから始める バイトオフセット・スクリプト化 ローテートで無効。行番号が原本座標でない
見ながらメモ 行番号と文脈 読む側と書く側が別アプリ grep -n -C/行番号の台帳 再生成が毎回全走査。引用の出所を検証できない
画面共有 相手の主体性 映像は共有されるが位置は共有されない 行番号をチャットで渡す 同じファイルを持っている前提。断片の外は見えない

4つとも、失われているのはデータではありません。原本は手元に残っています。 消えるのは、そのデータに対して「どこを・どういう順で・どう見たか」という調査の側の情報です。

そして右端の列が似た形をしているのは、4つとも原本の行番号が、人から人へ、日から日へ渡っていかないという一点に集約されるからです。行番号は原本の中でだけ意味を持つ座標で、切り出した瞬間・コピーした瞬間・閉じた瞬間に、ただの数字になります。

属人化は、人の能力差の問題として語られがちです。しかし実際に起きているのは、調査の状態を保存する場所が、どのツールにも用意されていないことです。だから優秀な人ほど頭の中に多くを溜め、その人が席を立つと多くが消えます。

必要な条件を3つに整理します。

  • 行番号が原本の座標のまま残ること — 絞り込んでも、日をまたいでも、人が変わっても、同じ数字が同じ行を指すこと
  • 検索条件が成果物として保存できること — 条件は結論と同じくらい引き継ぐ価値があります
  • 2回目以降が安いこと — 交代した人も、翌日の自分も、必ず「2回目」から始めます

冒頭の3行の申し送りに戻ります。あれは書き手が手を抜いたのではありません。書ける形をしていたものが、3行分しかなかっただけです。


使っている道具

私が開発している UwView(無料)は、巨大なテキストを開いた瞬間から表示・スクロール・検索できるビューアです。ファイル全体をメモリへ読み込まないので、RAM より大きいファイルでも開けます。索引はバックグラウンドで作られ、完成すると行番号が付きます(他のビューアの多くは索引が終わるまで先頭しか見えません)。分割も抽出もしないので、原本は1本のまま・無改変のまま扱えます。

  • 行番号を指定して跳ぶ: 4章の「41,284,471行目を見てください」が、そのまま操作になります。跳んだ先は原本なので、前後を好きなだけ広げて読めます。断片ではないので、相手はそこから自分の意思で動けます
  • 色分け(ハイライト): 1章で申し送りに書けなかったものです。語に色を付けて読み進める形が、そのまま調査の形になります(色分けの記事
  • 文字コードは開いたまま切り替えられます(UTF-8 / Shift-JIS(CP932) / EUC-JP / UTF-16 を自動判定)。交代した相手の環境で化けても、ファイルを作り直さずに合わせられます
  • 処理はすべて手元のマシンで完結します。調査対象のログを外部のサービスへ送りません

ここから先が UwView Pro の領分です。

  • 検索条件を保存して、翌日そこから再開する: 2章に直接効きます。条件そのものが成果物として残るので、翌朝は組み直しではなく当て直しから始められます。セッションも復元されるので、閉じたときの状態が翌日の出発点になります(アーカイブ×セッション復元の記事
  • 索引と圧縮を保存する: 一度開いたファイルは2回目以降行番号付きのまま瞬時に開き直せます(47.73GBのテキストで実測0.02〜0.07秒。特定環境での測定例で、環境により異なります)。交代した相手も、3日目の自分も、必ず「2回目」から始めます
  • 多段階検索(ドリルダウン): 1章の「Aで絞ってBを除いてCを探す」を、段として画面に残せます。タブに 語(件数) が並ぶので、絞り込みの順序そのものが見える形になります。そして原本の行番号は最後の段まで保持されます多段階検索の記事
  • フィルタPopupで別ウィンドウに並べる: 3章の「読む側と書く側の往復」に対して、絞り込み結果を並行して開いたまま原本を読めます(フィルタPopupの記事
  • 約1/9で保管しつつ検索できる: 引き継いだ人が過去分を見直す場面で、保管と再確認が両立します(第8回

正直に書いておきます。UwView はチームのコラボレーションツールではありません。

  • 共同編集も、リアルタイム共有もしません。 4章の「二人で同じ画面を見る」を置き換えるものではなく、それぞれが手元で同じ座標を開く形にするものです
  • 保存した条件やセッションは、そのマシンのローカルに残ります。 共有ストレージ経由で渡す運用は可能ですが、チーム共有の仕組みが組み込まれているわけではありません
  • チケット管理も、報告書の生成も、スクリーンショットの注釈もしません。 3章で作るのは引用の材料であって、報告書そのものではありません
  • マスキング機能はありません。 4章の機微情報の除去は、別の手段で行う必要があります
  • 対応するのはテキストです。バイナリのダンプやデータベースのファイルは対象外です

コマンドラインから同じことをする

v1.6.0 で uvp コマンドが付きました(無料版には uvf)。GUI と同じ .uwvz を使うので、CLI で作った索引はそのまま GUI でも効きます。この記事の4章に対応させると、こう書きます。

# 1章: 申し送りに「条件そのもの」を書く。同じ行に2語あるものだけを文脈つきで
uvp app.log 'ERROR' 'timeout' -C 5

# 2章: 翌朝、同じ条件を同じファイルへ当て直す(2回目以降は索引が効く)
uvp app.log.uwvz 'ERROR' 'timeout' -C 5

# 3章: 引用の材料を、圧縮したまま報告書用に書き出す
uvp app.log 'OutOfMemoryError' -C 10 -out findings-20260916.txt.gz

# 3章の続き: 例外の種類の内訳を先に出してから本文を書く
uvp app.log -uniq 'ERROR ([A-Za-z]+Exception)' -head 20

# 4章: 相手に渡すのは断片ではなくコマンド1行。同じ場所を GUI で開いてもらう
uvp app.log 'transaction_id=8f21' -C 20 -open

終了コードは grep と同じ 0=あり・1=なしに、2=上限に当たって打ち切った(既定は無制限。-limit N で上限を決めたときだけ)が加わります。if uvp app.log 'ERROR'; then がそのまま書けるので、2章の再確認スクリプトにそのまま混ぜられます。

正直に書くと、1問目は ripgrep のほうが 15〜20% 速いです(uvp は先に索引を作るため)。3GB程度でメモリに収まるファイルなら、2問目以降も rg のほうが速いままです。uvp が効くのは10GBを超えて、同じファイルに2回以上聞くときです(実測記事。Mac M4・外付けUSB SSD・OpenStreetMap XML での測定例で、環境により異なります)。

できるのは、見つけること・その場所を原本の座標で示すこと・同じ条件をもう一度当て直せる形で残すことです。交代のたびに調査が振り出しに戻っているなら、まず試してみてください。

そして、ストレージを専有している巨大ログを圧縮して保管し、さらに高速に検索したいなら UwView Pro をどうぞ。永続索引・圧縮キャッシュ検索・約1/9保管で、開き直しも検索も一段速くなります(全OS対応・買い切り/月額プランあり)。

リンク

  • 第1回: 巨大ファイルに沈む4つの定番ツールと、その先: https://uvp.y42u.net/blog/uwview-ps01-huge-file-tool-limits/
  • 第8回: 圧縮保管と検索の両立: https://uvp.y42u.net/blog/uwview-ps08-compressed-archive-search/
  • 第10回: 深夜2時の自分を助ける4つの仕込み: https://uvp.y42u.net/blog/uwview-ps10-oncall-night-preparation/
  • 第15回: コマンドライン職人芸の限界線4本: https://uvp.y42u.net/blog/uwview-ps15-cli-craft-limits/
  • 第16回: 保全・切り出し・改ざん対策の4原則: https://uvp.y42u.net/blog/uwview-ps16-log-as-evidence/
  • 第17回: 開発環境とログの4つの摩擦: https://uvp.y42u.net/blog/uwview-ps17-dev-env-log-friction/
  • 第20回: 監査対応を仕組みで乗り切る4項目: https://uvp.y42u.net/blog/uwview-ps20-audit-log-retrieval/
  • 翌日そこから開き直す(アーカイブ×セッション復元): https://uvp.y42u.net/blog/uwview-archive-session-restore-workflow/
  • 絞り込んだ先からさらに絞り込む(多段階検索): https://uvp.y42u.net/blog/uvp-drilldown-search/
  • フィルタPopupで文脈を保ったまま跳ぶ: https://uvp.y42u.net/blog/uwview-filter-popup-jump-save-context/
  • 色分けハイライト: https://uvp.y42u.net/blog/uwview-v11-color-highlighter/
  • uvp コマンドを付けました(ripgrep との実測比較): https://uvp.y42u.net/blog/uvp-cli-release-vs-ripgrep/
  • ソースコード(GitHub): https://github.com/amru195704/UwView

開発者より: アプリ・Kindle本・オープンソースの一覧は GitHub: amru195704 にまとめています。


お願い
本記事の情報は参考目的で掲載しており、正確性・完全性を保証するものではありません。掲載したログ例・行数・ファイルサイズ・件数はすべて説明のための例であり、特定の実在する案件やシステムを示すものではありません。コマンド例は環境(GNU/BSD、grepsedawk の実装差、シェルの種類、history の保存設定等)により調整が必要です。オプション名や既定値は必ず手元の man で確認してください。ログローテーションの挙動は logrotate の設定やアプリケーション側の実装により異なります。記載した実測値は特定の1環境での測定例であり、同じ結果を保証するものではありません。ディスクの種類・ファイルシステム・断片化・暗号化・ページキャッシュの状態・同時に動いている他のプロセスにより、結果は大きく変わります。ログの共有・持ち出し・マスキングの要否は、所属組織および委託元の規程、ならびに適用される法令に従ってください。誤記・不正確な情報がございましたら、コメント欄よりご指摘いただければ、確認のうえ修正いたします。

タイトルとURLをコピーしました