Skip to content

Commit 79ba355

Browse files
Fix negative trace substraction when using SetTimeout
1 parent 66256ef commit 79ba355

File tree

3 files changed

+60
-3
lines changed

3 files changed

+60
-3
lines changed

request.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,16 +1241,31 @@ func (r *Request) TraceInfo() TraceInfo {
12411241
return TraceInfo{}
12421242
}
12431243

1244+
ct.lock.RLock()
1245+
defer ct.lock.RUnlock()
1246+
12441247
ti := TraceInfo{
1245-
DNSLookup: ct.dnsDone.Sub(ct.dnsStart),
1246-
TLSHandshake: ct.tlsHandshakeDone.Sub(ct.tlsHandshakeStart),
1247-
ServerTime: ct.gotFirstResponseByte.Sub(ct.gotConn),
1248+
DNSLookup: 0,
1249+
TCPConnTime: 0,
1250+
ServerTime: 0,
12481251
IsConnReused: ct.gotConnInfo.Reused,
12491252
IsConnWasIdle: ct.gotConnInfo.WasIdle,
12501253
ConnIdleTime: ct.gotConnInfo.IdleTime,
12511254
RequestAttempt: r.Attempt,
12521255
}
12531256

1257+
if !ct.dnsStart.IsZero() && !ct.dnsDone.IsZero() {
1258+
ti.DNSLookup = ct.dnsDone.Sub(ct.dnsStart)
1259+
}
1260+
1261+
if !ct.tlsHandshakeDone.IsZero() && !ct.tlsHandshakeStart.IsZero() {
1262+
ti.TLSHandshake = ct.tlsHandshakeDone.Sub(ct.tlsHandshakeStart)
1263+
}
1264+
1265+
if !ct.gotFirstResponseByte.IsZero() && !ct.gotConn.IsZero() {
1266+
ti.ServerTime = ct.gotFirstResponseByte.Sub(ct.gotConn)
1267+
}
1268+
12541269
// Calculate the total time accordingly when connection is reused,
12551270
// and DNS start and get conn time may be zero if the request is invalid.
12561271
// See issue #1016.

request_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1927,6 +1927,28 @@ func TestTraceInfoOnTimeout(t *testing.T) {
19271927
assertEqual(t, true, tr.TotalTime == resp.Duration())
19281928
}
19291929

1930+
func TestTraceInfoOnTimeoutWithSetTimeout(t *testing.T) {
1931+
client := New().
1932+
SetTimeout(1 * time.Millisecond).
1933+
SetBaseURL("http://resty-nowhere.local").
1934+
EnableTrace()
1935+
1936+
resp, err := client.R().Get("/")
1937+
assertNotNil(t, err)
1938+
assertNotNil(t, resp)
1939+
1940+
tr := resp.Request.TraceInfo()
1941+
1942+
assertEqual(t, true, tr.DNSLookup == 0)
1943+
assertEqual(t, true, tr.ConnTime == 0)
1944+
assertEqual(t, true, tr.TLSHandshake == 0)
1945+
assertEqual(t, true, tr.TCPConnTime == 0)
1946+
assertEqual(t, true, tr.ServerTime == 0)
1947+
assertEqual(t, true, tr.ResponseTime == 0)
1948+
assertEqual(t, true, tr.TotalTime > 0)
1949+
assertEqual(t, true, tr.TotalTime == resp.Duration())
1950+
}
1951+
19301952
func TestDebugLoggerRequestBodyTooLarge(t *testing.T) {
19311953
formTs := createFormPostServer(t)
19321954
defer formTs.Close()

trace.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"crypto/tls"
1111
"fmt"
1212
"net/http/httptrace"
13+
"sync"
1314
"time"
1415
)
1516

@@ -95,6 +96,7 @@ func (ti TraceInfo) Clone() *TraceInfo {
9596
// with the same naming for easy understanding. Plus additional insights
9697
// [Request].
9798
type clientTrace struct {
99+
lock sync.RWMutex
98100
getConn time.Time
99101
dnsStart time.Time
100102
dnsDone time.Time
@@ -112,37 +114,55 @@ func (t *clientTrace) createContext(ctx context.Context) context.Context {
112114
ctx,
113115
&httptrace.ClientTrace{
114116
DNSStart: func(_ httptrace.DNSStartInfo) {
117+
t.lock.Lock()
115118
t.dnsStart = time.Now()
119+
t.lock.Unlock()
116120
},
117121
DNSDone: func(_ httptrace.DNSDoneInfo) {
122+
t.lock.Lock()
118123
t.dnsDone = time.Now()
124+
t.lock.Unlock()
119125
},
120126
ConnectStart: func(_, _ string) {
127+
t.lock.Lock()
121128
if t.dnsDone.IsZero() {
122129
t.dnsDone = time.Now()
123130
}
124131
if t.dnsStart.IsZero() {
125132
t.dnsStart = t.dnsDone
126133
}
134+
t.lock.Unlock()
127135
},
128136
ConnectDone: func(net, addr string, err error) {
137+
t.lock.Lock()
129138
t.connectDone = time.Now()
139+
t.lock.Unlock()
130140
},
131141
GetConn: func(_ string) {
142+
t.lock.Lock()
132143
t.getConn = time.Now()
144+
t.lock.Unlock()
133145
},
134146
GotConn: func(ci httptrace.GotConnInfo) {
147+
t.lock.Lock()
135148
t.gotConn = time.Now()
136149
t.gotConnInfo = ci
150+
t.lock.Unlock()
137151
},
138152
GotFirstResponseByte: func() {
153+
t.lock.Lock()
139154
t.gotFirstResponseByte = time.Now()
155+
t.lock.Unlock()
140156
},
141157
TLSHandshakeStart: func() {
158+
t.lock.Lock()
142159
t.tlsHandshakeStart = time.Now()
160+
t.lock.Unlock()
143161
},
144162
TLSHandshakeDone: func(_ tls.ConnectionState, _ error) {
163+
t.lock.Lock()
145164
t.tlsHandshakeDone = time.Now()
165+
t.lock.Unlock()
146166
},
147167
},
148168
)

0 commit comments

Comments
 (0)