cloud.google.com/goのリクエストをX-Rayでトレースしたい
#GCP #X-Ray #Go #cloud.google.com/go
cloud.google.com/goを使ってGCPへのリクエストをX-Rayのトレースとして表示したい。
が、思いがけずハマったので調査・workaroundを見つけたメモ。
2020/6/7 大きいライブラリで根が深そうなのでまだissueはあげていない。
なぜ今動かないのか
トークン取得時のリクエストにcontext.Contextを渡していないから
TokenSource.Token method should take in a Context · Issue #262 · golang/oauth2で議論されている
refs. oauth2.TokenSource oauth2.ReuseTokenSource() golang.org/x/oauth2/google.JWTAccessTokenSourceFromJSON()
APIリクエストに使うhttp.*Clientを組み立てる際、元となる http.*Client の Transport フィールドの実際の型が http.*Transport ではない 時、 http.DefaultTransport を尊重せずに新しいhttp.*Transportを返すから
結果、github.com/aws/aws-xray-sdk-go/xray.Client()が注入したhttp.RoundTripperが呼び出されない
ややこしいが http.*Client の Transport フィールドの型はhttp.RoundTripperであり、http.*Transportはそれを実装した一つの構造体型である
refs. google.golang.org/api/transport/http.defaultBaseTransport()
対策
code:code.go
import (
"context"
"net/http"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
func newClientWithToken(ctx context.Context, httpClient *http.Client, cred *google.Credentials) (*http.Client, error) {
if httpClient == nil {
httpClient = http.DefaultClient
}
token, err := cred.TokenSource.Token()
if err != nil {
return nil, err
}
staticSource := oauth2.StaticTokenSource(token)
client := oauth2.NewClient(ctx, staticSource)
client.CheckRedirect = httpClient.CheckRedirect
client.Jar = httpClient.Jar
client.Timeout = httpClient.Timeout
return client, nil
}
メモ
google.golang.org/api/transport/http.NewClient
→ golang.org/x/oauth2/transport/http.newTransport
→ google.golang.org/api/internal.Creds()
→ golang.org/x/oauth2/google.JWTAccessTokenSourceFromJSON()