💡 この記事の3行まとめ

  1. Dockerの長いログとスタックトレースは「縦に長い」だけでなく列で揃っているため、行をまたぐ範囲選択では列の対応が崩れます。
  2. 矩形で囲むと行と列の対応がそのまま保たれるので、「何番目のフレームで落ちたか」を数えながら読めます。
  3. Mac専用OCR翻訳『Zipp』は ⌃S で囲んで 0.3秒、Apple Visionによる端末内処理。無料でダウンロード(登録不要)、1日15回まで使えます。

📌 この記事の対象読者

  • docker logs や docker compose logs の出力が長く、どこから読めばいいか毎回迷う方
  • スタックトレースを翻訳したら、呼び出しの順番が追えなくなった経験のある方
  • 複数コンテナのログを並べて見比べる作業を、日常的にしている方

長いトレースが読めないのは、行数ではなく「列」が理由

Dockerのログは、1行が長いのではなく縦に積み上がる点に特徴があります。コンテナが落ちたときのターミナルには、数十行から数百行の出力が流れます。ここで多くの人が「長すぎて読めない」と感じますが、実際に詰まっているのは行数の多さではありません。

観察してみると、ログには列があります。docker compose logs の各行は、左から時刻、レベル、サービス名、| の区切り、そして本文という順に並びます。アプリケーションのスタックトレースは、at com.example... という呼び出しフレームが同じ深さで字下げされ、上から下へ「内側から外側」へ向かって並びます。構造化ログのJSONを行ごとに出している場合も、同じキーが同じ位置に来るように整形されています。

この列の揃いが、読み手にとっての唯一の手がかりです。ところが、行をまたいで範囲選択してコピーすると、この揃いが失われます。理由は単純で、選択は「文字の連続」として扱われるからです。20行を選択すると、20行分の文字が1本の長い文字列になり、翻訳サービスに渡ります。翻訳エンジンはそれを「段落」として扱い、行の区切りを文の区切りとして再解釈します。結果として、at で始まるフレームの連なりが1つの日本語の文章に溶けてしまい、どの行がどのフレームだったのか対応が取れなくなります。

さらに、訳文は日本語になるぶん文字数が変わり、折り返しの位置も変わります。原文では30行だったものが、訳文では18行になったり22行になったりします。行番号で会話していたチームでは、この時点で「3行目」という指示が通じなくなります。読めないのではなく、数えられない。これがDockerの長いログで起きている詰まりの正体です。

もう一つ見落とされがちなのが、比較の場面です。web と db の2つのコンテナのログを横に並べて、時刻の列を見比べることがあります。このとき列が揃っているから「dbが先に落ちて、webがその3秒後に落ちた」と読めます。1本の文字列に潰れた状態では、この前後関係は復元できません。


解決策:矩形で囲み、行と列の対応を保つ

Zippは文字を選択せず、画面に描画された結果をOCRで読み取ります。囲んだ範囲の行と列の構造がそのまま保たれるのが、長いトレースとの相性が良い理由です。

手順1:訳す列と訳さない列を決める

囲む前に、ログの列を3種類に仕分けます。

  • 訳さない列:時刻、レベル(INFO / ERROR)、サービス名、コンテナID。数字と短い英字が並ぶだけで、訳しても情報が増えません。
  • 訳す列:| より右の本文。ここに原因が書かれています。
  • 構造として読む列:at で始まるフレームの連なり。訳すというより、順番と深さを目で追う対象です。

この仕分けをしておくと、囲む範囲が自然に決まります。時刻列まで含めると、訳文の左側が数字で埋まり、本文が読みにくくなります。

手順2:⌃S を押し、本文列だけを縦長に囲む

⌃S(Control + S) を押してから、本文列の開始位置にカーソルを置き、下へドラッグします。横幅は「本文が入るぶんだけ」に絞り、時刻やレベルは外します。縦は、原因行から呼び出しフレームの末尾までを通します。

コツは、囲む前にターミナルのウィンドウを横に広げておくことです。折り返しが発生していると、見た目の1行が画面上では2行になり、列の位置がずれて見えます。広げられるなら広げる。広げられないなら、docker logs --tail 100 のように行数を絞ってから囲みます。--timestamps=false で時刻列を落とすのも有効です。

手順3:訳文で行数を数え、原文で深さを確認する

囲み終えると 0.3秒 で訳が最前面に表示されます。原文は隠れません。ここで行うのは、訳文を読み切ることではなく行の対応を取ることです。

訳文の各行が原文の各行に対応しているので、「上から7番目のフレームが、自分の書いたコードの位置だ」と数えられます。深さは字下げで判断できます。訳で意味を掴み、原文でファイル名と行番号を確認する。この往復が同じ画面で完結するため、ブラウザに切り替える移動が発生しません。移動がないことは、長いトレースを読むときの集中力に直結します。


長いログの読み方を比べる

【行と列の対応】
従来:1本の文字列になり、行の区切りが失われる
Zipp:囲んだ矩形の行構造がそのまま残る

【フレームの順序】
従来:訳文が段落になり、呼び出し順が追えない
Zipp:上から下への並びを保ったまま読める

【訳す列の選択】
従来:時刻やレベルも一緒に訳され、ノイズになる
Zipp:本文列だけを狙って囲める

【2つのログの比較】
従来:別々に貼るため前後関係が崩れる
Zipp:画面に並べて囲めば、時刻列で前後を確認できる

【ログの外部送出】
従来:トレース全体が外部サーバーへ渡る
Zipp:Apple Visionで端末内処理・画面画像の外部保存ゼロ

【試しやすさ】
従来:サービスごとに利用条件の確認が必要
Zipp:無料でダウンロード(登録不要)/1日15回まで


よくある質問(FAQ)

Q. 100行を超えるトレースでも矩形で囲めますか? A. 画面に映っている範囲が対象です。まず --tail で行数を絞り、原因行の前後だけを表示させてから囲むのが現実的です。全行を一度に読む必要はなく、多くの場合、最初の Caused by と直後の数フレームで原因は特定できます。

Q. 列がずれて見えるときはどうすればいいですか? A. 折り返しが起きている可能性が高いです。ウィンドウを広げる、フォントサイズを下げる、--no-log-prefix でプレフィックスを外す、の順に試してください。プレフィックスを外すと本文の開始位置が左に寄り、矩形の幅を狭くできます。

Q. 訳文が日本語になって行数が変わったら、対応は取れませんか? A. 訳文は原文の行のまとまりを保つため、極端に溶けることはありません。ただし行ごとの文字数は変わるので、行番号ではなく内容で対応を取るほうが確実です。ファイル名・関数名は原文のまま残るため、それが目印になります。

Q. 1日15回の範囲で、長いログは読めますか? A. 囲む範囲を絞れば1回で足ります。原因行と数フレーム、あるいは本文列の数十行を1回で囲む使い方が現実的です。全文を何度も訳すより、読む場所を決めてから囲むほうが回数も時間も節約できます。


揃っているから読める、という当たり前を守る

長いスタックトレースを前にして「英語が読めない」と感じたとき、実際に失われているのは語彙ではなく構造です。列が揃い、行が対応し、上から下へ呼び出しが並んでいる。その形が保たれているだけで、同じ英文が驚くほど追いやすくなります。

次のエラーで一度だけ、時刻列を外して本文列だけを ⌃S で縦に囲んでみてください。訳文の行が原文の行と対応していることを確かめられたら、長いログに対する見方が変わります。

▼ 無料でダウンロード(登録不要・1日15回まで)
zipp-mac.surge.sh

`