Goの net/http のClientにHAR形式でログ取れるTransportを作ってみた

Source: Goの net/http のClientにHAR形式でログ取れるTransportを作ってみた

vvakame vvakame -2019-10-03 16:52:41

sinmetalと話をして、GCSとかCloud Pub/Subは裏がREST APIなので、Transportで頑張ればプロダクションコードに手を加えずにモック実装にできるのでは?という会話があった。
そっちはそっちでやるといいと思うんだけど、裏側で行われている通信内容をとりあえずチェックしたくない?という気持ちになったのでやってみることにした。

HTTPリクエストの可視化というとまぁ HAR)ファイルじゃない?ということで net/http のClientのTransport(RoundTripper)にログ取りの処理を突っ込んでみるべ、という発想で作られたのがこのライブラリ。

https://github.com/vvakame/go-harlog


2019-10-03 16:53:03

とりあえず適当にGCSにアクセスしてHARファイルを作ってみる。
こんな感じの使い方です。
Transportを https://github.com/vvakame/go-harlog 製のものに置き換えて後は普通に実行する。
処理が終わったらJSONにしてどこかに出力しておく。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
ctx := context.Background()

hc, err := google.DefaultClient(ctx, storage.ScopeReadWrite)
if err != nil {
panic(err)
}

// inject HAR logger!
har := &harlog.Transport{
Transport: hc.Transport,
}
hc.Transport = har

client, err := storage.NewClient(
ctx,
option.WithHTTPClient(hc),
)
if err != nil {
panic(err)
}

bucket := client.Bucket(*bucket)

{
object := bucket.Object("2019-10-01-harlog/hello.txt")
r, err := object.NewReader(ctx)
if err != nil {
panic(err)
}
b, err := ioutil.ReadAll(r)
if err != nil {
panic(err)
}
fmt.Println(string(b))
}
{
object := bucket.Object("2019-10-01-harlog/goodnight.txt")
w := object.NewWriter(ctx)
_, err = w.Write([]byte("Good night, world!"))
if err != nil {
panic(err)
}
err = w.Close()
if err != nil {
panic(err)
}
}

// dump HAR file!
b, err := json.MarshalIndent(har.HAR(), "", " ")
if err != nil {
panic(err)
}
err = ioutil.WriteFile("gcs.har", b, 0644)
if err != nil {
panic(err)
}

HARファイルのインポート

ChromeのDevToolsとかで見れる。
連続して同じファイルをimportしようとすると黙って無視したりされて若干不親切なので、こっち使ったほうがいいかもしれない。


2019-10-03 16:53:06

GCSからファイルを読み出す処理のログの様子。
ヘッダ類、レスポンス、各種タイミングが記録されているのがわかる。

Headers

Response

Timing


2019-10-03 16:53:14

gRPCでも同様のことができるといいなーと思うけど、streamとかあるしHAR形式では難しいかな…。
REST APIとかでは便利だけどgRPCとかでは無力…!