122 lines
2.7 KiB
Go
122 lines
2.7 KiB
Go
// +build go1.8
|
|
|
|
package httpstat
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"net/http/httptrace"
|
|
"time"
|
|
)
|
|
|
|
// End sets the time when reading response is done.
|
|
// This must be called after reading response body.
|
|
func (r *Result) End(t time.Time) {
|
|
r.trasferDone = t
|
|
r.t5 = t // for Formatter
|
|
|
|
// This means result is empty (it does nothing).
|
|
// Skip setting value(contentTransfer and total will be zero).
|
|
if r.dnsStart.IsZero() {
|
|
return
|
|
}
|
|
|
|
r.contentTransfer = r.trasferDone.Sub(r.transferStart)
|
|
r.total = r.trasferDone.Sub(r.dnsStart)
|
|
}
|
|
|
|
func withClientTrace(ctx context.Context, r *Result) context.Context {
|
|
return httptrace.WithClientTrace(ctx, &httptrace.ClientTrace{
|
|
DNSStart: func(i httptrace.DNSStartInfo) {
|
|
r.dnsStart = time.Now()
|
|
},
|
|
|
|
DNSDone: func(i httptrace.DNSDoneInfo) {
|
|
r.dnsDone = time.Now()
|
|
|
|
r.DNSLookup = r.dnsDone.Sub(r.dnsStart)
|
|
r.NameLookup = r.dnsDone.Sub(r.dnsStart)
|
|
},
|
|
|
|
ConnectStart: func(_, _ string) {
|
|
r.tcpStart = time.Now()
|
|
|
|
// When connecting to IP (When no DNS lookup)
|
|
if r.dnsStart.IsZero() {
|
|
r.dnsStart = r.tcpStart
|
|
r.dnsDone = r.tcpStart
|
|
}
|
|
},
|
|
|
|
ConnectDone: func(network, addr string, err error) {
|
|
r.tcpDone = time.Now()
|
|
|
|
r.TCPConnection = r.tcpDone.Sub(r.tcpStart)
|
|
r.Connect = r.tcpDone.Sub(r.dnsStart)
|
|
},
|
|
|
|
TLSHandshakeStart: func() {
|
|
r.isTLS = true
|
|
r.tlsStart = time.Now()
|
|
},
|
|
|
|
TLSHandshakeDone: func(_ tls.ConnectionState, _ error) {
|
|
r.tlsDone = time.Now()
|
|
|
|
r.TLSHandshake = r.tlsDone.Sub(r.tlsStart)
|
|
r.Pretransfer = r.tlsDone.Sub(r.dnsStart)
|
|
},
|
|
|
|
GotConn: func(i httptrace.GotConnInfo) {
|
|
// Handle when keep alive is used and connection is reused.
|
|
// DNSStart(Done) and ConnectStart(Done) is skipped
|
|
if i.Reused {
|
|
r.isReused = true
|
|
}
|
|
},
|
|
|
|
WroteRequest: func(info httptrace.WroteRequestInfo) {
|
|
r.serverStart = time.Now()
|
|
|
|
// When client doesn't use DialContext or using old (before go1.7) `net`
|
|
// pakcage, DNS/TCP/TLS hook is not called.
|
|
if r.dnsStart.IsZero() && r.tcpStart.IsZero() {
|
|
now := r.serverStart
|
|
|
|
r.dnsStart = now
|
|
r.dnsDone = now
|
|
r.tcpStart = now
|
|
r.tcpDone = now
|
|
}
|
|
|
|
// When connection is re-used, DNS/TCP/TLS hook is not called.
|
|
if r.isReused {
|
|
now := r.serverStart
|
|
|
|
r.dnsStart = now
|
|
r.dnsDone = now
|
|
r.tcpStart = now
|
|
r.tcpDone = now
|
|
r.tlsStart = now
|
|
r.tlsDone = now
|
|
}
|
|
|
|
if r.isTLS {
|
|
return
|
|
}
|
|
|
|
r.TLSHandshake = r.tcpDone.Sub(r.tcpDone)
|
|
r.Pretransfer = r.Connect
|
|
},
|
|
|
|
GotFirstResponseByte: func() {
|
|
r.serverDone = time.Now()
|
|
|
|
r.ServerProcessing = r.serverDone.Sub(r.serverStart)
|
|
r.StartTransfer = r.serverDone.Sub(r.dnsStart)
|
|
|
|
r.transferStart = r.serverDone
|
|
},
|
|
})
|
|
}
|