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

分散トレーシングが切れる場所

切れたトレースを繋ぐ

TT Labで続きを見る

目標

トレースは1か所でもつながっていないと、全体が役に立たなくなります。ところが、途切れてもエラーが出ないため、ダッシュボードを開いて見るまでは誰も気づきません。

このラボでは、すでに途切れている3つのサービスを渡し、それをつなげてもらいます。

開始

cp /opt/lab/trace/* . && chmod +x run.sh
./run.sh            # a → b → c 로 요청 하나를 흘린다
python3 tree.py     # 이어졌는지 본다

ファイル

ファイル 役割
svc.py サービス1つ。バグが1つあります
run.sh 3つを起動し、リクエストを1つ流します
tree.py ログを読んで、つながっているかを判定します

知っておくこと

run.shはサービスを終了させるときにpkill -f svc.pyを使いません。そのパターンはスクリプトを実行したシェルのコマンドラインにも一致してしまい、自分自身を終了させてしまうからです。PIDを書き留めておき、それだけを終了させます。

traceparent

00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
│  │                                │                │
│  trace id (16바이트)               부모 span         플래그
버전

ステップ

  1. 途切れていることの確認 → 01-broken.txt
  2. どこで、なぜ → 02-where.md
  3. つなぐ → 採点ツールが直接実行して確認
  4. 形式を読む → 04-format.md
  5. サンプリングの一貫性 → 05-sampling.txt
  6. 同時リクエスト → 06-concurrent.txt
  7. 整理 → 07-notes.md

途切れた状態を目で確認する

/opt/lab/trace/を作業ディレクトリにコピーして./run.shを実行し、python3 tree.pyの結果を01-broken.txtに残してください。

cp /opt/lab/trace/* . && chmod +x run.shで始めます。3つのサービス(a→b→c)にリクエストが1つ流れます。

症状は実際の現場と同じです。各サービスはトレースを正しく送っているのに、つながりません。ダッシュボードにはスパン1つだけのトレースが大量にたまります。

どこで、なぜ途切れるのかを突き止める

svc.pyを読み、どの行が問題かを02-where.mdに書いてください。なぜその1行がトレースを途切れさせるのかもあわせて書きます。

次のサービスへリクエストを送る箇所を見てください。受け取った側は、ヘッダーがなければ新しいtrace idを作ります。それが正しい動作です。問題は送る側です。

トレースが途切れる箇所は、ほとんどの場合呼び出す側です。受け取る側のコードをいくら見ても見つかりません。

1つにつなぐ

svc.pyを修正して、3つのサービスが1つのtrace idを共有し、親子関係がつながるようにしてください。

送信するリクエストにtraceparentヘッダーを付けます。形式は버전-trace-내span-플래그です(プレースホルダーはバージョン、自分のspan、フラグです)。親の位置に入れるのは、受け取った親ではなく、今の自分のspanです。ここでよく間違えます。

採点ツールは直接実行して、trace idの種類が1つ、ルートが1つ、親を見つけられないスパンが0個であることを確認します。

traceparentを分解して読む

04-format.mdにtraceparentの4つの要素がそれぞれ何かを書き、ステップ3のログから実際の値を1つ例として挙げてください。

00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01。先頭から、バージョン、trace id(16バイト)、親span(8バイト)、フラグです。

長さが決まっているので、目でも検証できます。trace idが32文字でなければ、その時点で間違っています。

サンプリングは1回だけ決める

ルートサービスがフラグを00(収集しない)で開始しても、3つのサービスがすべて同じフラグを残すことを確認し、05-sampling.txtに残してください。

決定はルートで1回行い、そのまま運び続けます。途中で決め直すとトレースが半分になります。前半は収集され後半はないトレースほど、デバッグの邪魔になるものはありません。

ルートで開始フラグを変えて実行したあと、tree.pyのフラグの行を残してください。

同時に複数流しても混ざらないか

リクエストを3つ同時に流し、それぞれが別々に完全なトレースになっていることを確認して、06-concurrent.txtに残してください。

run.shを参考にサービスを起動したあと、curl3つを&で同時に送ってください。正しければ、trace idが3種類、各traceにスパンが3個、ルートが3個、孤立スパンが0個です。

ここで壊れる典型的な原因は、コンテキストをグローバル変数に入れることです。リクエスト1つでテストすると問題なく動き、トラフィックが加わった瞬間にトレースが互いに混ざります。言語ごとにリクエスト単位のストレージが別にあるのは、そのためです。

3つを整理する

07-notes.mdに3行以上。トレースが途切れる箇所、親の位置に何を入れるか、サンプリングの決定をどこで行うか。

本文に호출、부모、샘플링が含まれている必要があります(韓国語でそれぞれ「呼び出し」「親」「サンプリング」を意味する語です)。