trace.go raw
1 // Copyright (c) 2015-2024 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
2 // resty source code and usage is governed by a MIT style
3 // license that can be found in the LICENSE file.
4
5 package resty
6
7 import (
8 "context"
9 "crypto/tls"
10 "net"
11 "net/http/httptrace"
12 "sync"
13 "time"
14 )
15
16 //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
17 // TraceInfo struct
18 //_______________________________________________________________________
19
20 // TraceInfo struct is used to provide request trace info such as DNS lookup
21 // duration, Connection obtain duration, Server processing duration, etc.
22 type TraceInfo struct {
23 // DNSLookup is the duration that transport took to perform
24 // DNS lookup.
25 DNSLookup time.Duration
26
27 // ConnTime is the duration it took to obtain a successful connection.
28 ConnTime time.Duration
29
30 // TCPConnTime is the duration it took to obtain the TCP connection.
31 TCPConnTime time.Duration
32
33 // TLSHandshake is the duration of the TLS handshake.
34 TLSHandshake time.Duration
35
36 // ServerTime is the server's duration for responding to the first byte.
37 ServerTime time.Duration
38
39 // ResponseTime is the duration since the first response byte from the server to
40 // request completion.
41 ResponseTime time.Duration
42
43 // TotalTime is the duration of the total time request taken end-to-end.
44 TotalTime time.Duration
45
46 // IsConnReused is whether this connection has been previously
47 // used for another HTTP request.
48 IsConnReused bool
49
50 // IsConnWasIdle is whether this connection was obtained from an
51 // idle pool.
52 IsConnWasIdle bool
53
54 // ConnIdleTime is the duration how long the connection that was previously
55 // idle, if IsConnWasIdle is true.
56 ConnIdleTime time.Duration
57
58 // RequestAttempt is to represent the request attempt made during a Resty
59 // request execution flow, including retry count.
60 RequestAttempt int
61
62 // RemoteAddr returns the remote network address.
63 RemoteAddr net.Addr
64 }
65
66 //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
67 // ClientTrace struct and its methods
68 //_______________________________________________________________________
69
70 // clientTrace struct maps the [httptrace.ClientTrace] hooks into Fields
71 // with the same naming for easy understanding. Plus additional insights
72 // [Request].
73 type clientTrace struct {
74 lock sync.RWMutex
75 getConn time.Time
76 dnsStart time.Time
77 dnsDone time.Time
78 connectDone time.Time
79 tlsHandshakeStart time.Time
80 tlsHandshakeDone time.Time
81 gotConn time.Time
82 gotFirstResponseByte time.Time
83 endTime time.Time
84 gotConnInfo httptrace.GotConnInfo
85 }
86
87 func (t *clientTrace) createContext(ctx context.Context) context.Context {
88 return httptrace.WithClientTrace(
89 ctx,
90 &httptrace.ClientTrace{
91 DNSStart: func(_ httptrace.DNSStartInfo) {
92 t.lock.Lock()
93 t.dnsStart = time.Now()
94 t.lock.Unlock()
95 },
96 DNSDone: func(_ httptrace.DNSDoneInfo) {
97 t.lock.Lock()
98 t.dnsDone = time.Now()
99 t.lock.Unlock()
100 },
101 ConnectStart: func(_, _ string) {
102 t.lock.Lock()
103 if t.dnsDone.IsZero() {
104 t.dnsDone = time.Now()
105 }
106 if t.dnsStart.IsZero() {
107 t.dnsStart = t.dnsDone
108 }
109 t.lock.Unlock()
110 },
111 ConnectDone: func(net, addr string, err error) {
112 t.lock.Lock()
113 t.connectDone = time.Now()
114 t.lock.Unlock()
115 },
116 GetConn: func(_ string) {
117 t.lock.Lock()
118 t.getConn = time.Now()
119 t.lock.Unlock()
120 },
121 GotConn: func(ci httptrace.GotConnInfo) {
122 t.lock.Lock()
123 t.gotConn = time.Now()
124 t.gotConnInfo = ci
125 t.lock.Unlock()
126 },
127 GotFirstResponseByte: func() {
128 t.lock.Lock()
129 t.gotFirstResponseByte = time.Now()
130 t.lock.Unlock()
131 },
132 TLSHandshakeStart: func() {
133 t.lock.Lock()
134 t.tlsHandshakeStart = time.Now()
135 t.lock.Unlock()
136 },
137 TLSHandshakeDone: func(_ tls.ConnectionState, _ error) {
138 t.lock.Lock()
139 t.tlsHandshakeDone = time.Now()
140 t.lock.Unlock()
141 },
142 },
143 )
144 }
145