Slide 1

Slide 1 text

2024年7月19日 @ クラシコムさん 大量の OpenTelemetry スパンを Cloud Trace に送りつけそうになった話 カヤックSRE 市川恭佑(@ebi-yade)

Slide 2

Slide 2 text

Who is @ebi-yade 󰳕 IT エンジニアをやっています ● カヤック SRE 3年目(新卒入社) ● Google Cloud Observability が好き ● 最近ありがたいことに?仕事が増加傾向 💪 筋トレはじめました ● パーソナル初心者 ● 荷重スクワットが楽しい ● 上半身は伸び代チョモランマ

Slide 3

Slide 3 text

OpenTelemetry、やってますか?

Slide 4

Slide 4 text

OpenTelemetry とは 複雑なトラブルシューティングの 属人化を排除する取り組み “オブザーバビリティ” → テレメトリシグナルの取り扱いを標準化 テレメトリシグナルの例: ● ログ ● トレース ● メトリクス ● プロファイラ

Slide 5

Slide 5 text

OpenTelemetry とは 複雑なトラブルシューティングの 属人化を排除する取り組み “オブザーバビリティ” → テレメトリシグナルの取り扱いを標準化 テレメトリシグナルの例: ● ログ ● トレース ● メトリクス ● プロファイラ 今日のトピック

Slide 6

Slide 6 text

トレースとは ● どの処理にどのくらい時間かかったかを可視化したもの ● ↓それぞれのボックスを “スパン” という

Slide 7

Slide 7 text

OpenTelemetry Go SDK による初期化の例 exporter, err := googletrace.New(googletrace.WithProjectID(projectID)) if err != nil { ... } resource, err := // 略 tracerProvider := sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter), // 出力先 == Google Cloud Trace sdktrace.WithResource(resource), sdktrace.WithSampler( // スパンを間引く sdktrace.ParentBased( // 基本的に親スパンの設定に従う sdktrace.TraceIDRatioBased(defaultSampleRatio), // 親スパンが存在しなかった場合 => 一定の確 率 ), ), )

Slide 8

Slide 8 text

ことの発端 exporter, err := googletrace.New(googletrace.WithProjectID(projectID)) if err != nil { ... } resource, err := // 略 tracerProvider := sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter), // 出力先 == Google Cloud Trace sdktrace.WithResource(resource), sdktrace.WithSampler( // スパンを間引く sdktrace.ParentBased( // 基本的に親スパンの設定に従う sdktrace.TraceIDRatioBased(defaultSampleRatio), // 親スパンが存在しなかった場合 => 一定の確 率 ), ), ) defaultSampleRatio := 1.0 sdktrace.AlwaysSample()と等価

Slide 9

Slide 9 text

検証環境のトレース一覧 正常時

Slide 10

Slide 10 text

検証環境のトレース一覧 あっ......😇

Slide 11

Slide 11 text

ご清聴ありがとうございました

Slide 12

Slide 12 text

という訳にもいかないので 気を取り直して状況の整理......

Slide 13

Slide 13 text

ことの発端 exporter, err := googletrace.New(googletrace.WithProjectID(projectID)) if err != nil { ... } resource, err := // 略 tracerProvider := sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter), // 出力先 == Google Cloud Trace sdktrace.WithResource(resource), sdktrace.WithSampler( // スパンを間引く sdktrace.ParentBased( // 基本的に親スパンの設定に従う sdktrace.TraceIDRatioBased(defaultSampleRatio), // 親スパンが存在しなかった場合 => 一定の確 率 ), ), ) 親スパンが存在しない場合の挙動を 「常にサンプルする」にした

Slide 14

Slide 14 text

そもそも「親スパンがある」という状態とは 以下のどれかに該当する ● 計装済み関数の子孫として呼び出されており、親はサンプルされている ● 計装済み関数の子孫として呼び出されており、親はサンプルされていない ● クライアントがサンプルされているスパンを伝播してきた ● クライアントがサンプルされていないスパンを伝播してきた サンプルの成否は 存在とは別概念

Slide 15

Slide 15 text

そもそも「親スパンがある」という状態とは 以下のどれかに該当する ● 計装済み関数の子孫として呼び出されており、親はサンプルされている ● 計装済み関数の子孫として呼び出されており、親はサンプルされていない ● クライアントがサンプルされているスパンを伝播してきた ● クライアントがサンプルされていないスパンを伝播してきた サンプルの成否は 存在とは別概念 親スパンがない → 存在しない (当たり前)

Slide 16

Slide 16 text

親スパンがある代表的なケース ロードバランサ        リクエスト リクエストスコープの スパンを開始

Slide 17

Slide 17 text

親スパンがない代表的なケース ロードバランサ        リクエスト 起動処理 バッファ付きの 非同期処理 グレースフル シャットダウン

Slide 18

Slide 18 text

問題のスパンたち google.devtools.cloudtrace.v2.TraceService/BatchWriteSpans

Slide 19

Slide 19 text

問題のスパンたち google.devtools.cloudtrace.v2.TraceService/BatchWriteSpans スパンを送ったよ! というスパン (非同期バッファ)

Slide 20

Slide 20 text

親スパンがない代表的なケース ロードバランサ        リクエスト 起動処理 バッファ付きの 非同期処理 グレースフル シャットダウン

Slide 21

Slide 21 text

親スパンがない代表的なケース ロードバランサ        リクエスト バッファ付きの 非同期処理 ここで Cloud Trace に スパンが送られていた

Slide 22

Slide 22 text

親スパンがない場合のサンプリングレートを1にした結果 スパンを送信! オブザーバビリティ バックエンド ● Cloud Trace ● AWS X-Ray ● はてな Vaxila

Slide 23

Slide 23 text

親スパンがない場合のサンプリングレートを1にした結果 スパンを送信! オブザーバビリティ バックエンド ● Cloud Trace ● AWS X-Ray ● はてな Vaxila バッファ付き非同期処理 → 親スパンがない

Slide 24

Slide 24 text

親スパンがない場合のサンプリングレートを1にした結果 スパンを送信! オブザーバビリティ バックエンド ● Cloud Trace ● AWS X-Ray ● はてな Vaxila スパンを送信した!というスパンを送信!

Slide 25

Slide 25 text

親スパンがない場合のサンプリングレートを1にした結果 スパンを送信! オブザーバビリティ バックエンド ● Cloud Trace ● AWS X-Ray ● はてな Vaxila スパンを送信した!というスパンを送信! スパンを送信した!というスパンを送信!

Slide 26

Slide 26 text

親スパンがない場合のサンプリングレートを1にした結果 スパンを送信! オブザーバビリティ バックエンド ● Cloud Trace ● AWS X-Ray ● はてな Vaxila スパンを送信した!というスパンを送信! スパンを送信した!というスパンを送信! スパンを送信した!というスパンを送信!

Slide 27

Slide 27 text

親スパンがない場合のサンプリングレートを1にした結果 スパンを送信! オブザーバビリティ バックエンド ● Cloud Trace ● AWS X-Ray ● はてな Vaxila スパンを送信した!というスパンを送信! スパンを送信した!というスパンを送信! スパンを送信した!というスパンを送信! スパンを送信した!というスパンを送信! ……

Slide 28

Slide 28 text

まとめ

Slide 29

Slide 29 text

まとめ 「親が無いスパン」はしっかり間引こう ● バッファ付き非同期処理など、意識が向きにくい場所で開始される ● そもそも OpenTelemetry の自動計装コード自体が認知されにくい ● 一応トレース送信クライアントの設定でオプトアウトも可能ではある 触れてないけど大事なこと ● SDK で OpenTelemetry Trace するならとりあえず ParentBased ● さもなくば宙ぶらりんなスパンが爆誕する可能性