このトピックでは、v0.26.0 より前の Asynq バージョンでトレースの継続性を維持する方法について説明します。
ソリューション
v0.26.0 より前の Asynq バージョンでは、SpanContext を伝播するためのキャリアが Task 構造体に含まれていません。トレースの継続性を維持するには、ペイロード内で手動でトレースコンテキストを渡す必要があります。
// Task は、実行される作業の単位を表します。
type Task struct {
// typename は、実行されるタスクのタイプを示します。
typename string
// payload は、タスクの実行に必要なデータを保持します。
payload []byte
// opts は、タスクのオプションを保持します。
opts []Option
// w は、タスクの ResultWriter です。
w *ResultWriter
}たとえば、Task ペイロードのデータ構造体が次のようになっているとします。
type WelcomeEmailPayload struct {
UserID int `json:"user_id"`
Email string `json:"email"`
Username string `json:"username"`
}以下のように、コンテキストを渡すためのフィールドを構造体に追加します。
type WelcomeEmailPayload struct {
UserID int `json:"user_id"`
Email string `json:"email"`
Username string `json:"username"`
Header map[string]string `json:"header"`
}Task を作成する前に、span を作成してコンテキストをペイロードに書き込みます。
var task asynq.Task
tracer := otel.GetTracerProvider().Tracer("")
opts := append([]tracex.SpanStartOption{}, tracex.WithSpanKind(tracex.SpanKindClient))
// これはデモです。作成したスパンのトレース情報を本文に書き込んでサーバー側に送信します。必要に応じてコードを調整してください。
ctx, span := tracer.Start(context.Background(), "Push Task", opts...)
var headerMap propagation.MapCarrier
headerMap = make(map[string]string)
otel.GetTextMapPropagator().Inject(ctx, headerMap)
// スパンコンテキストをヘッダーに設定します。
for k, v := range headerMap {
task.Header[k] = v
}
defer span.End()
//... タスクをサーバーにプッシュしますTask を取得する際に、コンテキストを復元します。
var headerMap propagation.MapCarrier
headerMap = make(map[string]string)
ctxRequest := context.Background()
// タスクヘッダーを取得します。
var task asynq.Task
for k, v := range task.Header {
headerMap[k] = v
}
xxCtx := otel.GetTextMapPropagator().Extract(ctxRequest, headerMap)
tracer := otel.GetTracerProvider().Tracer("")
opts := append([]trace.SpanStartOption{}, trace.WithSpanKind(trace.SpanKindServer))
_, span := tracer.Start(xxCtx, "Recv Task", opts...)
defer span
//... その他この手動の方式で、span コンテキストを伝播します。
アプリケーションをコンパイルした後、アプリケーションのプローブに対して OpenTelemetry の設定を有効にします。変更を反映させるには、アプリケーションを再起動してください。