Upgrade to Pro — share decks privately, control downloads, hide ads and more …

分散トレースを理解する! Trace Context 解体新書

分散トレースを理解する! Trace Context 解体新書

Kento Kimura

May 22, 2024
Tweet

Video

More Decks by Kento Kimura

Other Decks in Technology

Transcript

  1. Datadog Japan G.K. Kento Kimura(𝕏: @AoToLog_), Keisuke Sakasai(𝕏: @k6s4i53rx) May

    22nd, CNDS 2024 pre-event in Tokyo 分散トレースを理解する! Trace Context 解体新書 GENERAL USE
  2. Self-Introduction: Co-Speaker • 所属:Datadog Japan    Technical Solutions / Sales Engineer

    • コミュニティ(出没): ◦ Jagu'e'r, JAWS, CloudNative, ex-AWS Jr. Champ • 肩書:Google Cloud Partner Top Engineer 2023-24  2022-23 APN All AWS Certifications Engineer  AWS Community Builder(Cloud Operations, since 2024) • 登壇:CloudNative Days Fukuoka 2023 pre-event in Tokyo 「サーバレス関数って何を監視すればいいの?」 • 属性:逆井さんの先輩になってしまった一般人 木村 健人 (Kento Kimura) Datadog Japan GK Technical Solutions Sales Engineering
  3. Self-Introduction: Co-Speaker • 所属:Datadog Japan    Technical Solutions / Sales Engineer

    • コミュニティ: ◦ OpenTelemetry Meetup スタッフ ◦ Google Cloud Champion Innovators コミュニティ 逆井 啓佑 (Keisuke Sakasai) Datadog Japan GK Technical Solutions Sales Engineering ◆ 技術書典 16  俺たちのxQL完全ガイド  - PromQL / LogQL / TraceQL 編 -  日程:5/26(日)  場所:池袋・サンシャインシティ
  4. 話すこと・話さないこと 話すこと • 分散トレースとは何か • トレースとスパンデータの構造 • HTTP のトレースの伝搬 •

    OpenTelemetry の話 話さないこと • オブザーバビリティとは何か • トレース以外のテレメトリー • HTTP 以外のトレースの伝搬 • Datadog の話 登壇のきっかけ CloudNative Days にプロポーザルを出すにあたり Datadog に Join する逆井さんとあれこれ 会話していた。個人的に、「分散トレースなんもわからん」期に突入していたので、これを機 に徹底的に調べ上げ発表することに…! 理論は木村、実践は逆井でお送りします😄
  5. 分散トレースの歴史 分散トレースが主流となったのは、2010年の Google より発表された Dapper の論文から その後、オープンソースプロジェクトとして Zipkin, Jaeger、商用ソリューションも多く登場 2019年には標準化とオープンソースプロジェクトの統合が達成され現在に至る

    2010 Dapper Google の大規模分散システムのト レーシング技術 2012 Zipkin(OpenZipkin) Twitter 社のアプリパフォーマンス チューニングツールのOSS化 2017 Jaeger   Uber による分散トレース技術 CNCF に寄贈されたプロジェクト 2016・2017 OpenTracing OpenCensus   いろいろあって統合 2019 W3C Trace Context トレース伝搬仕様の標準化 2019 OpenTelemetry 唯一のオープンソース標準 引用: A History of Distributed Tracing
  6. 分散トレースの要素① 分散トレースを実現するためには、トレースを収集するための仕組みを施す「計装」、 それらのトレースデータを信頼性・効率性を担保してバックエンドに送信する「転送」、 収集されたトレースデータをバックエンドで分析する「可視化」が必要 Input Output Service 計装 転送 Backend

    可視化 ◆ 参考 ・OpenTelemetryのここ4年の流れhttps://speakerdeck.com/ymotongpoo/opentelemetry-in-last-4-plus-years ・計測の手間を省きたい!OpenTelemetry に見る”自動計装”のイマ: https://speakerdeck.com/k6s4i53rx/getting-started-auto-instrumentation-with-opentelemetry
  7. スパンデータ解剖 (OpenTelemetry) • スパンコンテキスト(Span Context): トレース間で伝搬するスパンの情報。TraceContext • スパン名(Span name): スパンの名前。スパンによって表される作業を簡潔に識別する。

    • スパン種別(SpanKind): スパンの種別。親子関係を識別する。SERVER/CLIENT etc • 開始/終了時間(Timestamp): 開始時刻はスパンの作成時。終了時刻は操作の終了時。 • 属性(Attributes): リクエストと他テレメトリを関連付けるキーと値のペア。スパンタグ。 • スパンリンク(Span links): 他のスパンコンテキストへのリンク。トレース内外のスパンで可能。 • イベント(Events): イベント名・タイムスタンプ・属性で定義される。 • ステータス(Status): OK/Error を指定。Error の場合は Description がつけられる。 デフォルトは Unset となる。 Span name(SpanKind: SOMETHING, Status: Unset) 開始時間 終了時間 Root span(Parent span) Child span スパン コンテキスト スパン コンテキスト トレース コンテキスト
  8. トレースの可視化: フレームグラフ 主にプロファイラで用いられるビュー Pros • トレースが一画面に収まりやすい • N+1 処理等の大量のスパンを可視化できる •

    スパンの前後・親子関係を把握しやすい Cons • 並列・非同期処理の可視化が難しい clint /api /auth /payment /email API /pool /message /dispatch /send-email UserDB
  9. トレースの可視化: スパンリスト スパンの検索や実行時間を把握するビュー Pros • スパンの検索やソートができる • 数値で実行時間や割合を確認できる Cons •

    感覚的なアプリ処理の把握が難しい • スパンの前後関係がわからない • あくまでも補助的なビュー Span name Duration Exec % Client └/client 6.32ms 13.3% Shopping └/api 5.48ms 6.6% Auth └/auth 1.05ms 1.9% UserDB └UserDB 0.93ms 14.7% Payment └/payment 1.93ms 22.1% └API 0.53ms 8.4% Email ├/email 2.06ms 12% ├/pool 1.13ms 0% ├/message 1.13ms 0% └/dispatch 1.13ms 0% Send email └/send-email 1.30ms 20.6%
  10. トレースの可視化: トレースマップ・ツリー サービスの因果関係を可視化するビュー Pros • サービスの関係がわかりやすい • リクエストやエラー等が把握しやすい Cons •

    スパンの前後関係がわからない • スパンの実行時間がわからない • あくまでも俯瞰的なビュー client Shopping Auth Payment email Send email UserDB
  11. W3C Trace Context 分散トレースのコンテキスト情報を伝播するための HTTP ヘッダーと値の形式の定義。 主に TraceParent, TraceState の2つの伝搬フィールドに分割される。

    TraceParent • すべてのベンダーが理解できる共通の形式で、受信リクエストの情報を伝搬する   traceparent: {version}-{trace-id}-{parent-id}-{trace-flag} 例)traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01 TraceState • ベンダー固有の形式で、追加のベンダー固有のトレースの識別情報を伝搬する   tracestate: {Key1}={Value1}, {Key2}={Value2} 例)tracestate: dd=ss, ot=12345
  12. W3C Trace Context による標準化 なぜ標準化? • 複数プロバイダーのデータリンクによる相互運用性の向上 • ベンダー固有のメタデータの保持・伝搬の保証 •

    トレースを扱うステークホルダー間への業界標準の提供 トレースの転送(MUST) • TraceParent, TraceState ヘッダーは必ず伝搬し、トレースが破損しないようにする必要がある • 通信プロトコルに準拠した伝搬方法がある(後述) トレースへの参加(CAN) • TraceState ヘッダーを修正し、独自情報を含めても良い • TraceState は Key=Value 形式で、利用できる文字・記号・長さに制限がある
  13. 伝搬(Propagation) HTTP/gRPC • W3C Trace Context は HTTP Header での伝搬方法に焦点を当てた標準

    • gPRC はHTTP/2 上に実装された RPC プロトコルで、Protocol Buffer を インターフェイス定義言語 ( IDL ) とメッセージ交換形式として定義できる その他(Trace Context Protocols Registry) • Trace Context Binary Protocol • 符号なし8ビット整数値のビットとしてバイナリ形式で伝搬 • Trace Context AMQP Protocol(FPWD: First Public Working Draft) • traceparent: binary, tracestate: string として伝搬するように定義 • Trace Context MQTT Protocol(FPWD: First Public Working Draft) • User properties で伝搬するように定義
  14. 非標準化: B3 Multiple/Single header Zipkin(Open Zipkin) で利用されているフォーマット オープンソースプロジェクトのため、商用プロダクトが準拠していることが多い マルチヘッダー •

    B3 属性は複数 HTTP header で伝搬されるのが一般的 • {SamplingState}は Accept: 1, Deny: 0, Debug:d が設定される シングルヘッダー   b3: {TraceId}-{SpanId}-{SamplingState}-{ParentSpanId} 例)b3: bd520db18d3c49648ad0b58825c68f21-c07f5482e1da4b86-0-e1747be2140a4de2 • サンプリングを行う場合はサンプリング状態の b3: {SamplingState} のみを伝搬する 例)X-B3-TraceId: bd520db18d3c49648ad0b58825c68f21   X-B3-SpanId: c07f5482e1da4b86   X-B3-ParentSpanId: e1747be2140a4de2   X-B3-Sampled: 0 X-B3-TraceId: {TraceId} X-B3-SpanId: {SpanId} X-B3-ParentSpanId:{ParentSpanId} X-B3-Sampled: {SamplingState}
  15. 標準化: W3C distributed context(Baggage) 分散リクエストまたはワークフロー実行に関連付けられた アプリケーション定義のプロパティのセットを表現・伝達するための標準 Trace Context との関係 •

    Baggage は分散トレースを行うかに関係なく利用できる HTTP header による伝搬 • Baggage: アプリケーション定義のプロパティ表現と伝達の標準化 • TraceState: 分散トレース シナリオを有効にするために必要なメタデータの表現と伝播を標準化 baggage: key1=value1;property1;property2, key2 = value2, key3=value3; propertyKey=propertyValue
  16. OpenTelemetry とは • テレメトリーデータの収集・送信の標準仕様を定めている ◦ ログ / トレース / メトリクス

    / プロファイル • 様々な言語の計装ライブラリを提供 ◦ Go、Java、Python、C++、JavaScript… • OpenTelemetry Collector の開発 今回のテーマである 分散トレース も、 OpenTelemetry のライブラリを用いて計装できる Service OTel Collector 監視 バックエンド OTLP OTLP OTLP = OpenTelemetry Protocol 例) ・OTLP ・Datadog Exporter ・Google Cloud Exporter
  17. Tracer Span Tracer Provider OpenTelemetry Trace の構成要素 ( 概要 )

    Propagator Resource Span Processor Span Exporter Samplar SpanContext Attributes Span Kind Event 等 等 Span Span ◆ 参考 ・OpenTelemetry Trace Spec: https://opentelemetry.io/docs/specs/otel/trace/api/ ・OpenTelemetryこれまでとこれから: https://bit.ly/20220311-o11yconf-otel ・分散トレーシングとOpenTelemetryのススメ @ OCHaCafe Season7 Span
  18. OpenTelemetry Trace の構成要素 ( 概要 ) Resource Span Processor Span

    Exporter Samplar SpanContext Attributes Span Kind Event 等 等 スパンに共通的に付与するタグ(サービス名、Version 等) スパンを処理: BatchSpan Processor / SimpleSpan Processor スパンを送信 スパンをサンプリング: Always On, Off / Random Span Span Span Span Tracer Tracer Provider Propagator ◆ 参考 ・OpenTelemetry Trace Spec: https://opentelemetry.io/docs/specs/otel/trace/api/ ・OpenTelemetryこれまでとこれから: https://bit.ly/20220311-o11yconf-otel ・分散トレーシングとOpenTelemetryのススメ @ OCHaCafe Season7
  19. OpenTelemetry Trace の構成要素 ( 概要 ) Resource Span Processor Span

    Exporter Samplar SpanContext Attributes Span Kind Event 等 等 トレース ID やスパン ID 等 スパンごとに付与するタグ スパンの種別(Client, Server, Internal) イベント名 / Timestamp / イベントログ Span Span Span Span Tracer Tracer Provider Propagator ◆ 参考 ・OpenTelemetry Trace Spec: https://opentelemetry.io/docs/specs/otel/trace/api/ ・OpenTelemetryこれまでとこれから: https://bit.ly/20220311-o11yconf-otel ・分散トレーシングとOpenTelemetryのススメ @ OCHaCafe Season7
  20. Propagator OpenTelemetry Trace の構成要素 ( 概要 ) Resource Span Processor

    Span Exporter Samplar SpanContext Attributes Span Kind Event 等 等 W3C Trace Context、b3 single header など Span Span Span Span Tracer Tracer Provider ◆ 参考 ・OpenTelemetry Trace Spec: https://opentelemetry.io/docs/specs/otel/trace/api/ ・OpenTelemetryこれまでとこれから: https://bit.ly/20220311-o11yconf-otel ・分散トレーシングとOpenTelemetryのススメ @ OCHaCafe Season7
  21. OpenTelemetry Trace の構成要素 ( 概要 ) Resource Span Processor Span

    Exporter Samplar SpanContext Attributes Span Kind Event 等 等 スパンに共通的に付与するタグ(サービス名、Version 等) スパンを処理: BatchSpan Processor / SimpleSpan Processor スパンを送信 スパンをサンプリング: Always On, Off / Random トレースIDやスパンIDなど スパンごとに付与するタグ スパンの種別(Client, Server, Internal) イベント名 / Timestamp / イベントログ Span Span Span Span Tracer Tracer Provider Propagator W3C Trace Context、b3 single header など
  22. OpenTelemetry Trace の構成要素 ( 概要 ) サービス A サービス B

    サービス Z ・ ・ ・ ・ Propagator の設定に基づき、 トレースコンテキストが伝播 トレース バックエンド clint /api /auth /payment /email API /pool /message /dispatch /send-email UserDB ◆ 参考 ・OpenTelemetry Trace Spec: https://opentelemetry.io/docs/specs/otel/trace/api/ ・OpenTelemetryこれまでとこれから: https://bit.ly/20220311-o11yconf-otel ・分散トレーシングとOpenTelemetryのススメ @ OCHaCafe Season7
  23. OpenTelemetry Trace のコンテキスト伝播 サービス間のトレースコンテキストの交換は Propagator が担う • W3C Trace Context:

    go.opentelemetry.io/otel/propagation • b3 single header: go.opentelemetry.io/contrib/propagators/b3 Propagator は仕様として Extract / Inject メソッドを持つ • Extract は HTTP の場合、ヘッダからトレースコンテキストを抽出 • Inject は同様に、ヘッダにトレースコンテキストを注入 <Header> Trace ID Span ID 受信 送信 リクエスト リクエスト <Header> Trace ID Span ID Extract Inject ※ キャリア構造体は省略
  24. OpenTelemetry Trace のコンテキスト伝播 W3C Trace Context での Propagator の実装(extract) func

    (tc TraceContext) extract(carrier TextMapCarrier) trace.SpanContext { // ヘッダーからトレース情報を取り出す h := carrier.Get(traceparentHeader) // traceparentHeader="traceparent" … // スパンコンテキストの構造体を定義 var scc trace.SpanContextConfig // 構造体にヘッダーのトレース ID をセット if !extractPart(scc.TraceID[:], &h, 32) { return trace.SpanContext{} } // 構造体にヘッダーのスパン ID をセット if !extractPart(scc.SpanID[:], &h, 16) { return trace.SpanContext{} } // ヘッダーから取り出したトレース情報をアクティブなスパンコンテキストとして設定 sc := trace.NewSpanContext(scc) github.com/open-telemetry/opentelemetry-go/blob/main/propagation/trace_context.go#L80-L128
  25. OpenTelemetry Trace のコンテキスト伝播 otelhttp のようなパッケージは、 ヘッダーの解析、スパンコンテキストへの設定を行ってくれる計装ライブラリ github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/net/http/otelhttp/handler.go#L134 helloHandler := func(w

    http.ResponseWriter, req *http.Request) { … // 何かしらの処理 _, _ = io.WriteString(w, "Hello, world!\n") } // otelhttp でラップ // 計装 = ヘッダからトレース情報を抽出して、スパンコンテキストに設定 otelHandler := otelhttp.NewHandler(http.HandlerFunc(helloHandler), "Hello") // サーバーの起動 http.Handle("/hello", otelHandler) err = http.ListenAndServe(":8080", nil) github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/net/http/otelhttp/example/server/server.go#L82-L97
  26. OpenTelemetry Trace のコンテキスト伝播 (補足) • ここまでコード含めて見てきたように、 トレースコンテキストを取り回すことで分散トレースを実現 • HTTP じゃなくても、トレースコンテキストをサービス間でやり取りできればトレースを繋げる

    ことができる(非同期通信の分散トレース) ◦ otelsalama (Kafka の Consumer / Producer 用の計装ライブラリ) 参考:Apache Kafka を使った非同期処理で分散トレーシングをする with OpenTelemetry: https://zenn.dev/k6s4i53rx/articles/2fa37a293cf228
  27. OpenTelemetry Trace のコンテキスト伝播 (補足) • ここまでコード含めて見てきたように、 トレースコンテキストを取り回すことで分散トレースを実現 • HTTP じゃなくても、トレースコンテキストをサービス間でやり取りできればトレースを繋げる

    ことができる(非同期通信の分散トレース) ◦ otelsalama (Kafka の Consumer / Producer 用の計装ライブラリ) 参考:Apache Kafka を使った非同期処理で分散トレーシングをする with OpenTelemetry: https://zenn.dev/k6s4i53rx/articles/2fa37a293cf228 前半学んだ座学を OpenTelemetry の実装に触れながら見ました。
  28. トレースに付与する属性情報 • トレーススパンの属性情報 ◦ サービス単位で付与: Resource / スパン単位で付与: Attribute ◦

    情報量(ディメンション、カーディナリティ)を増やすことで、 テレメトリーデータの探索の切り口が増え、オブザーバビリティを高めることができる • 方法 ◦ ❶ 手動で Resource や Attribute を付与する ◦ ❷ 計装ライブラリの利用   https://opentelemetry.io/ecosystem/registry/ ◦ ❸ OpenTelemetry Collector で Processor を使う ▪ Kubernetes Attributes Processor ▪ Resource Detection Processor • Resource Detection Processor でホスト名と(ディメンション)が付与 20 種類(カーディナリティ)のホストがあり、探索の観点を増やすことができる OTel Collector mongo otelmongo サービスA ホスト名 (例) Resource Detection Processor ❶ ❸ ❷
  29.  留意点 • Baggage に渡すだけでは Span の属性情報には含まれない点 • Baggage の肥大化リスク •

    参考:"Ask Miss O11y: Baggage in OTel" honeycomb.io/blog/ask-miss-o11y-opentelemetry-baggage Baggage の利用について • コンテキスト伝播として baggage 使用 ◦ Baggage はキーバリュー形式のデータ構造 ◦ ヘッダ名は "baggage"。仕様は W3C Baggage に準拠 • ユースケース例 ◦ User IDs, Product IDs, and origin IPs ◦ feature flags の実装 otel.SetTextMapPropagator( propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, ), ) opentelemetry.io/docs/concepts/signals/baggage/
  30. 分散トレースと他のテレメトリーの関連付け テレメトリー同士の関連付けもオブザーバビリティを高める上で重要 • テレメトリー同士の関連付け ◦ ログ ⇔ トレース: ログにトレース ID

    を付与 ◦ メトリクス ⇔ トレース: タイムスタンプやトレースエグザンプラーを使用 • プロファイルとトレースもトレース情報を使って紐付け。 モニタリングツールによってはダッシュボード上で遷移(一例) ◦ Datadog ◦ Grafana Pyroscope(v1.2.0)で "Trace to profile" リリース https://github.com/grafana/otel-profiling-go ▪ TracerProvider を拡張して、 Span 生成時にサンプルしたプロファイルに SpanID を付与して、Grafana 上で紐付ける仕組み https://grafana.com/docs/pyroscope/next/configure-client/trace-span-profiles/go-span-profiles/ トレース プロファイル