125 lines
3.8 KiB
Go
125 lines
3.8 KiB
Go
// Copyright (c) 2015-2024 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
|
|
// resty source code and usage is governed by a MIT style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package resty
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"net"
|
|
"net/http/httptrace"
|
|
"time"
|
|
)
|
|
|
|
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
|
|
// TraceInfo struct
|
|
//_______________________________________________________________________
|
|
|
|
// TraceInfo struct is used to provide request trace info such as DNS lookup
|
|
// duration, Connection obtain duration, Server processing duration, etc.
|
|
type TraceInfo struct {
|
|
// DNSLookup is the duration that transport took to perform
|
|
// DNS lookup.
|
|
DNSLookup time.Duration
|
|
|
|
// ConnTime is the duration it took to obtain a successful connection.
|
|
ConnTime time.Duration
|
|
|
|
// TCPConnTime is the duration it took to obtain the TCP connection.
|
|
TCPConnTime time.Duration
|
|
|
|
// TLSHandshake is the duration of the TLS handshake.
|
|
TLSHandshake time.Duration
|
|
|
|
// ServerTime is the server's duration for responding to the first byte.
|
|
ServerTime time.Duration
|
|
|
|
// ResponseTime is the duration since the first response byte from the server to
|
|
// request completion.
|
|
ResponseTime time.Duration
|
|
|
|
// TotalTime is the duration of the total time request taken end-to-end.
|
|
TotalTime time.Duration
|
|
|
|
// IsConnReused is whether this connection has been previously
|
|
// used for another HTTP request.
|
|
IsConnReused bool
|
|
|
|
// IsConnWasIdle is whether this connection was obtained from an
|
|
// idle pool.
|
|
IsConnWasIdle bool
|
|
|
|
// ConnIdleTime is the duration how long the connection that was previously
|
|
// idle, if IsConnWasIdle is true.
|
|
ConnIdleTime time.Duration
|
|
|
|
// RequestAttempt is to represent the request attempt made during a Resty
|
|
// request execution flow, including retry count.
|
|
RequestAttempt int
|
|
|
|
// RemoteAddr returns the remote network address.
|
|
RemoteAddr net.Addr
|
|
}
|
|
|
|
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
|
|
// ClientTrace struct and its methods
|
|
//_______________________________________________________________________
|
|
|
|
// clientTrace struct maps the [httptrace.ClientTrace] hooks into Fields
|
|
// with the same naming for easy understanding. Plus additional insights
|
|
// [Request].
|
|
type clientTrace struct {
|
|
getConn time.Time
|
|
dnsStart time.Time
|
|
dnsDone time.Time
|
|
connectDone time.Time
|
|
tlsHandshakeStart time.Time
|
|
tlsHandshakeDone time.Time
|
|
gotConn time.Time
|
|
gotFirstResponseByte time.Time
|
|
endTime time.Time
|
|
gotConnInfo httptrace.GotConnInfo
|
|
}
|
|
|
|
func (t *clientTrace) createContext(ctx context.Context) context.Context {
|
|
return httptrace.WithClientTrace(
|
|
ctx,
|
|
&httptrace.ClientTrace{
|
|
DNSStart: func(_ httptrace.DNSStartInfo) {
|
|
t.dnsStart = time.Now()
|
|
},
|
|
DNSDone: func(_ httptrace.DNSDoneInfo) {
|
|
t.dnsDone = time.Now()
|
|
},
|
|
ConnectStart: func(_, _ string) {
|
|
if t.dnsDone.IsZero() {
|
|
t.dnsDone = time.Now()
|
|
}
|
|
if t.dnsStart.IsZero() {
|
|
t.dnsStart = t.dnsDone
|
|
}
|
|
},
|
|
ConnectDone: func(net, addr string, err error) {
|
|
t.connectDone = time.Now()
|
|
},
|
|
GetConn: func(_ string) {
|
|
t.getConn = time.Now()
|
|
},
|
|
GotConn: func(ci httptrace.GotConnInfo) {
|
|
t.gotConn = time.Now()
|
|
t.gotConnInfo = ci
|
|
},
|
|
GotFirstResponseByte: func() {
|
|
t.gotFirstResponseByte = time.Now()
|
|
},
|
|
TLSHandshakeStart: func() {
|
|
t.tlsHandshakeStart = time.Now()
|
|
},
|
|
TLSHandshakeDone: func(_ tls.ConnectionState, _ error) {
|
|
t.tlsHandshakeDone = time.Now()
|
|
},
|
|
},
|
|
)
|
|
}
|