opentelemetry-go: exec.Commandで外部コマンドを呼ぶ時にトレースコンテキストを伝搬させる
exec.Commandで外部コマンドを起動する時にトレースコンテキストを伝搬させてみました
今回のコード例
環境変数+propagation.TraceContextを利用することで伝搬させてみました。
解説
httpやgRPCの場合のコンテキスト伝搬
こちらの記事にあるように、呼び出す側/呼び出される側の両方で以下のようにPropagatorを設定した上でotelhttpやotelgrpcなどのインターセプターを利用します。
otel.SetTextMapPropagator( propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, ), )
exec.Command
で外部コマンドを起動する時にはotelhttpやotelgrpcのようなインターセプターがありませんので自前でInject/Extractする必要があります。
どうやってトレースコンテキストを渡す?
W3C TraceContextのような仕様がないか探したのですが、いくつかの実装はあるものの仕様としてはまだない模様でした。
そこで参考としてequinix-labs/otel-cliでの環境変数経由でトレースコンテキストを参照する部分の実装をみたところ、
となっていました。
これならpropagation.TraceContextの実装が使えるのでは?
上記の仕様で渡すのであればpropagation.TraceContextが使えそうです。
propagation.TraceContextは引数で渡されたpropagation.TextMapCarrierに対して読み書きを行います。
環境変数をなんらかの形でラップしてpropagation.TextMapCarrierの形にした上でInject/Extractを呼べばなんとかできそうです。
やってみた
改めて今回のコード例はこちらに置いています。
親コマンド側では以下のようにotel.GetTextMapPropagator().Inject()
した上で環境変数を組み立てています。
https://github.com/yamamoto-febc/otel-env-context/blob/6db0d50cbf473c8c3095413657da234a57c63ddb/cmd/otel-parent/main.go#L47-L51
// 親コマンド側 // Propagatorに指定されているpropagation.TraceContextを用いてトレースコンテキストをenvCarrierに書き出し envCarrier := propagation.MapCarrier{} otel.GetTextMapPropagator().Inject(ctx, envCarrier) // 書き出したトレースコンテキストを環境変数に設定 for _, key := range envCarrier.Keys() { cmd.Env = append(cmd.Env, key+"="+envCarrier.Get(key)) }
子コマンド側ではotel.GetTextMapPropagator().Extract()
してあげます。
https://github.com/yamamoto-febc/otel-env-context/blob/4f30a8c453d64b567eecae2301226327114f1a5e/cmd/otel-child/main.go#L27-L33
// 子コマンド側 envCarrier := propagation.MapCarrier{ "traceparent": os.Getenv("traceparent"), "tracestate": os.Getenv("tracestate"), } // 環境変数からトレースコンテキストを抽出 parentCtx := otel.GetTextMapPropagator().Extract(context.Background(), envCarrier) // トレース開始 ctx, span := otel.Tracer(instrumentationName).Start(parentCtx, "child")
これでいい感じにトレースコンテキストの伝搬ができてるはずです。
終わりに
もっといいやり方があれば是非教えてください。
以上です。
参考にしたサイト
christina04.hatenablog.com blog.cybozu.io www.w3.org github.com