Slide 1

Slide 1 text

徳富 博(プラットフォームエンジニアリング1G) サービス連携の”謎解き”を可能にする Datadogによる分散トレース導入の第一 歩 @yannKazu1 SRE NEXT 2025

Slide 2

Slide 2 text

自己紹介

Slide 3

Slide 3 text

自己紹介 徳富 博(@yannKazu1) - 所属: タイミー プラットフォームエンジ ニアリングチーム 1G - 好きな技術: Go, Ruby, TypeScript, AWS, … - 野菜を育ててます

Slide 4

Slide 4 text

分散トレーシングについて

Slide 5

Slide 5 text

分散トレーシングとは??

Slide 6

Slide 6 text

分散トレーシングは、システムをまたいだリクエストの流れをエンドツーエンドで可視化 ・追跡する技術です。

Slide 7

Slide 7 text

Propagator? SpanContext? Carrier? サービス間の分散トレーシングを行うとなるといろんな概念が出てきて よくわからなくなる

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

HTTP Headerはどう言う形式で送ればいい?

Slide 10

Slide 10 text

サービス間の分散トレース情報連携の主な方式(HTTPヘッダー、Datadogの場合) 🐶 Datadog 独自形式(datadog) ● x-datadog-trace-id: ● x-datadog-parent-id: ● x-datadog-sampling-priority: ● Datadog APM向けのデフォルト形式 🌐 W3C Trace Context(標準規格、 tracecontext) ● traceparent: --- ● OpenTelemetryなど多くのベンダーが対 応 ⚠ B3(非推奨) 🔹 B3 Multi(b3multi) ● X-B3-TraceId: ● X-B3-SpanId: ● X-B3-ParentSpanId: (任意) ● X-B3-Sampled: 0 または 1 ● Zipkin互換。レガシー用途。複数ヘッダ形 式。 🔸 B3 Single(b3 single header, b3single) ● b3: -- ● 軽量・1ヘッダで伝播。モダンなgRPCや HTTP/2と相性が良い。

Slide 11

Slide 11 text

こういう実装をすれば良いのか? と思った人も多いのではないでしょうか

Slide 12

Slide 12 text

悪くはないがメンテナンス性はよくない ● ヘッダー仕様が変わったとき毎回修正が必要 ● それぞれのサービスが Datadog形式なのか、 tracecontext 形式なのかを意識して実装しないといけないのがつらい。

Slide 13

Slide 13 text

ddtraceには(otel sdkにもあるが省略)、トレース情報をヘッダーに埋め込 んだり取り出したりする仕組み(Inject/Extract)メソッドが用意されて いる

Slide 14

Slide 14 text

送信側

Slide 15

Slide 15 text

受信側

Slide 16

Slide 16 text

Inject/Extractを使えば、環境変数を変えるだけで、tracecontext 形式・datadog形式・両対応など、柔軟に伝搬形式を切り替えられ ます。 ヘッダー伝搬形式の切り替え( ddtrace) ● DD_TRACE_PROPAGATION_STYLE ○ Inject/Extract両方に適用 ○ デフォルトは datadog,tracecontext(両対応) ● DD_TRACE_PROPAGATION_STYLE_INJECT / ..._EXTRACT ○ 各々個別に指定も可能 → Inject/Extractを使えば、簡単に複数の形式(ddtrace形式・tracecontext形 式など)に対応させることができ、形式を意識しなくてよくなる

Slide 17

Slide 17 text

トレース情報をヘッダーに埋め込んだり取り出したりする時 は自前実装ではなくSDKの Inject/Extractを使おう!

Slide 18

Slide 18 text

ところでここって何をやっているんだ?

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

まずはHTTPHeadersCarrier

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

● HTTPHeadersCarrierはhttp.Headerのラッパー ● TextMapWirter, TextMapReaderインターフェースを満たしてい る https://github.com/DataDog/dd-trace-go/blob/cde886e584560f55306cbe0d302eb54d66b88cfc/ddtrace/tracer/textmap.go#L24-L27

Slide 24

Slide 24 text

● TextMapWriter Interface は Set メソッドを持っていて、トレースコンテキ ストを HTTP ヘッダーに詰めるときに使う。 ● TextMapReader Interface は ForeachKey メソッドを持っていて、HTTP ヘッダーから トレースコンテキストを取り出すときに使う。 https://github.com/DataDog/dd-trace-go/blob/0e41cff05e9ed88c9ace780284322acbcbc37574/ddtrace/tracer/propagator.go#L25-L38

Slide 25

Slide 25 text

今回は HTTPHeadersCarrier を使用したが... ● Inject / Extract で使う Carrier(キャリア) は TextMapWriter / TextMapReader インターフェースを満たしていれば OK ● そのため、自作の構造体を使ってカスタマイズした Carrier を作ることも可能

Slide 26

Slide 26 text

tracer(Inject/Extract)

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

tracer.InjectはPropagator.Inejectを呼び出す https://github.com/DataDog/dd-trace-go/blob/0e41cff05e9ed88c9ace780284322acbcbc37574/ddtrace/tracer/tracer.go#L841

Slide 29

Slide 29 text

tracer.ExtractはPropagator.Extractを呼び出す https://github.com/DataDog/dd-trace-go/blob/0e41cff05e9ed88c9ace780284322acbcbc37574/ddtrace/tracer/tracer.go#L878

Slide 30

Slide 30 text

Propagator.Inejectの実装 https://github.com/DataDog/ dd-trace-go/blob/b7f198c8d bd42202c46fe191ca68b931 009ab042/ddtrace/tracer/te xtmap.go#L428-L471 TextMapWriter の Set メソッ ドを使って、トレースコンテキ ストを HTTP ヘッダーに書き 込んでいる

Slide 31

Slide 31 text

Propagator.Extractの実装 https://github.com/DataDog/ dd-trace-go/blob/b7f198c8d bd42202c46fe191ca68b9310 09ab042/ddtrace/tracer/text map.go#L510-L571 TextMapReader の ForeachKey メソッドを 使って、HTTP ヘッダーか らトレースコンテキストを読 み取っている

Slide 32

Slide 32 text

● Tracerの Inject や Extract によるトレースコンテキストの詰め替え処理は、実 際には Propagator が担当します。 ● Propagator は、トレースコンテキストを HTTP ヘッダー(HTTP Header Carrier 使用時)に埋め込む・取り出すロジックを持ちます。 ● Propagatorの処理ではCarrier の set メソッドを使って、ヘッダーにトレース情 報を書き込み、foreachKey メソッドを使って、ヘッダーからトレース情報を読 み取ります。

Slide 33

Slide 33 text

今回は組み込まれているPropagatorを使用してますが Propagator は インターフェースを満たしていれば何でも 指定できる。

Slide 34

Slide 34 text

Propagator interface の定義 https://github.com/DataDog/dd-trace-go/blob/0e41cff05e9ed88c9ace780284322acbcbc37574/ddtrace/tracer/propagator.g o#L14-L20

Slide 35

Slide 35 text

tracer.Start 時に WithPropagator オプションを指定することで、独自の Propagator を適用することも可能。

Slide 36

Slide 36 text

Propagator / Carrier を自作する場面 ● Datadogが対応していないプロトコルや形式を使う場合 ● トレース情報の伝搬を制御したい場合 ● カスタムフォーマットが必要な場合

Slide 37

Slide 37 text

まとめ

Slide 38

Slide 38 text

まとめ ● サービス間連携 ○ トレース情報をHTTPヘッダーに手動で仕込むのではなく、各SDKが提供する Inject/Extractメソッドを使用しましょう。 ○ これにより、環境変数(DD_TRACE_PROPAGATION_STYLE)を切り替えるだけ で、Datadog形式、tracecontext形式など柔軟にヘッダー伝搬形式に対応でき ます。 ● 詳細な仕組み: PropagatorとCarrier ○ Inject/Extractメソッドは内部でPropagatorを呼び出します。 ○ PropagatorはSpanContextの情報をCarrier通じてHTTP Headerに 詰めたり、読み取ってSpanContextを生成する役割を担います。 ○ Carrierは、HTTPヘッダーなどの情報伝達媒体を抽象化したラッパーであり、 TextMapWriter(書き込み用)とTextMapReader(読み取り用)インターフェース を実装します。 ○ インターフェースを満たしていれば、カスタムのPropagatorやCarrierを実 装することも可能です。

Slide 39

Slide 39 text

Give distributed tracing a try!