2024/12/9 DNSやTLSフェーズでかかった時間をOTelで計測する
ソフトウェアが外部のWeb APIを利用しているとさまざまなことが起こります
Web API が一時的に利用できない状態となりソフトウェアが使用できなくなる
Web API のレイテンシが悪化してソフトウェアの利用者が使いづらくなる
外部から提供される Web API なので我々ではハンドリングできません
とはいえ、問題は利用している Web API にあるのでしょうか?
ソフトウェアがリクエストしている段で問題があることはないのでしょうか?
問題をすぐに外部要因にする癖がつくのはよくありませんね。まずは切り分けをしましょう
Web API のリクエストは外部サービスに届いてからが外部要因です
なので、リクエストにおける DNS や TLS フェーズで問題が起こっていないかということは事前に確認すべきでしょう
安直に考えて、ソフトウェアが Web API へリクエストを送信する様を模倣しようとすると、curlがすぐ頭に浮かびます ただ curl -v verboseオプションを使っても、DNS や TLS フェーズの経過時間はわかりません
ほかの手段として考えられるのはネットワークデバッグで利用するような Charles, Wireshark ですが、今回やりたいことにはtoo much過ぎる気がします (そして準備が面倒というイメージがある すでにチームのアプリケーションは OTel で計装しているのでレポジトリで http リクエストを書き始めればすぐ計装が可能ですし、ローカルでは zipkin が起動するのでトレースも確認もできます 基本的な手順は:
1. OTel の基礎的なセットアップ
resource, exporter の設定をしてグローバルな trace provider を指定します
code:oteldo.go
attrs := resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("example.httpclient"),
)
resc, err := resource.New(ctx,
resource.WithAttributes(attrs.Attributes()...),
resource.WithTelemetrySDK(),
)
exporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure())
if err != nil {
return nil, err
}
provider := trace.NewTracerProvider(
trace.WithBatcher(exporter),
trace.WithSampler(trace.AlwaysSample()),
trace.WithResource(resc),
)
otel.SetTracerProvider(provider)
2. http.Client を作成する際に、otelhttp.NewTransport を使います。http.RoundTripper をラップし Span コンテキストをアウトバウンドなリクエストヘッダーに追加しメトリクスを拡張、otelhttptrace.NewClientTrace がリクエストのSpanを記録する ClientTrace 実装を返す。基本的はそのまま使っているので、今回やりたき DNS, TLS などはここでSpanがトレースに追加されます
code:httpclient.go
client := http.Client{
Transport: otelhttp.NewTransport(
http.DefaultTransport,
otelhttp.WithClientTrace(func(ctx context.Context) *httptrace.ClientTrace {
return otelhttptrace.NewClientTrace(ctx)
}),
),
}
サンプルでは、zipkin だけではなく jaeger も使って exporter を2つ設定しているので各 UI でそれぞれ以下のように見ることができます
https://scrapbox.io/files/67565dc64fdf6300da7effd2.png
https://scrapbox.io/files/67565dcaa36f48b73e085cdd.png
注意したい点は、go net/http パッケージにおけるリクエストのDNS解決のデフォルトはGo実装になっています
もしホストの getaddressinfo(3) を使いたい場合は GODEBUG=netdns=cgo のオプションでビルドする必要がある
今日は以上です