httptrace
httptrace
1. 初始化 httptrace.ClientTrace
httptraceClientTrace
httptrace.ClientTrace
ClientTrace
type ClientTrace struct {
// GetConn is called before a connection is created or
// retrieved from an idle pool. The hostPort is the
// "host:port" of the target or proxy. GetConn is called even
// if there's already an idle cached connection available.
GetConn func(hostPort string)
// GotConn is called after a successful connection is
// obtained. There is no hook for failure to obtain a
// connection; instead, use the error from
// Transport.RoundTrip.
GotConn func(GotConnInfo)
[...]
// DNSStart is called when a DNS lookup begins.
DNSStart func(DNSStartInfo)
// DNSDone is called when a DNS lookup ends.
DNSDone func(DNSDoneInfo)
// ConnectStart is called when a new connection's Dial begins.
// If net.Dialer.DualStack (IPv6 "Happy Eyeballs") support is
// enabled, this may be called multiple times.
ConnectStart func(network, addr string)
// ConnectDone is called when a new connection's Dial
// completes. The provided err indicates whether the
// connection completedly successfully.
// If net.Dialer.DualStack ("Happy Eyeballs") support is
// enabled, this may be called multiple times.
ConnectDone func(network, addr string, err error)
[...]
}
ClientTrace
package main
import (
"fmt"
"log"
"net/http"
"net/http/httptrace"
)
func main() {
req, _ := http.NewRequest(http.MethodGet, "http://example.com", nil)
clientTrace := &httptrace.ClientTrace{
GetConn: func(hostPort string) { fmt.Println("starting to create conn ", hostPort) },
DNSStart: func(info httptrace.DNSStartInfo) { fmt.Println("starting to look up dns", info) },
DNSDone: func(info httptrace.DNSDoneInfo) { fmt.Println("done looking up dns", info) },
ConnectStart: func(network, addr string) { fmt.Println("starting tcp connection", network, addr) },
ConnectDone: func(network, addr string, err error) { fmt.Println("tcp connection created", network, addr, err) },
GotConn: func(info httptrace.GotConnInfo) { fmt.Println("connection established", info) },
}
}
2. 使用 httptrace.WithClientTrace 创建上下文
httptrace.WithClientTrace
func WithClientTrace(ctx context.Context, trace *ClientTrace) context.Context
WithClientTrace
这是我们需要添加到示例中的内容
clientTraceCtx := httptrace.WithClientTrace(req.Context(), clientTrace)
3. 将 httptrace.ClientTrace 与我们的 HTTP 客户端一起使用
我们的最终结果如下。 定义客户端跟踪钩子,使用客户端跟踪创建上下文并将其传递到我们的请求对象中。
package main
import (
"fmt"
"log"
"net/http"
"net/http/httptrace"
)
func main() {
req, _ := http.NewRequest(http.MethodGet, "http://example.com", nil)
clientTrace := &httptrace.ClientTrace{
GetConn: func(hostPort string) { fmt.Println("starting to create conn ", hostPort) },
DNSStart: func(info httptrace.DNSStartInfo) { fmt.Println("starting to look up dns", info) },
DNSDone: func(info httptrace.DNSDoneInfo) { fmt.Println("done looking up dns", info) },
ConnectStart: func(network, addr string) { fmt.Println("starting tcp connection", network, addr) },
ConnectDone: func(network, addr string, err error) { fmt.Println("tcp connection created", network, addr, err) },
GotConn: func(info httptrace.GotConnInfo) { fmt.Println("connection established", info) },
}
clientTraceCtx := httptrace.WithClientTrace(req.Context(), clientTrace)
req = req.WithContext(clientTraceCtx)
_, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
}
预期结果如下
starting to create conn example.com:80
starting to look up dns {example.com}
done looking up dns {[{93.184.216.34 } {2606:2800:220:1:248:1893:25c8:1946 }] false}
starting tcp connection tcp 93.184.216.34:80
tcp connection created tcp 93.184.216.34:80
connection established {0xc000010090 false false 0s}
这些只是我们可以用来在 Go 中跟踪传出 HTTP 请求的可能事件的一个子集。 但是正如我们从这个示例中看到的那样,这对于跟踪正在发生的事情和对我们的 http 客户端进行故障排除已经非常有用