github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/resty/trace.go (about) 1 // Copyright (c) 2015-2021 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 "time" 13 ) 14 15 //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ 16 // TraceInfo struct 17 //_______________________________________________________________________ 18 19 // TraceInfo struct is used provide request trace info such as DNS lookup 20 // duration, Connection obtain duration, Server processing duration, etc. 21 type TraceInfo struct { 22 // DNSLookup is a duration that transport took to perform 23 // DNS lookup. 24 DNSLookup time.Duration 25 26 // ConnTime is a duration that took to obtain a successful connection. 27 ConnTime time.Duration 28 29 // TCPConnTime is a duration that took to obtain the TCP connection. 30 TCPConnTime time.Duration 31 32 // TLSHandshake is a duration that TLS handshake took place. 33 TLSHandshake time.Duration 34 35 // ServerTime is a duration that server took to respond first byte. 36 ServerTime time.Duration 37 38 // ResponseTime is a duration since first response byte from server to 39 // request completion. 40 ResponseTime time.Duration 41 42 // TotalTime is a duration that total request took end-to-end. 43 TotalTime time.Duration 44 45 // IsConnReused is whether this connection has been previously 46 // used for another HTTP request. 47 IsConnReused bool 48 49 // IsConnWasIdle is whether this connection was obtained from an 50 // idle pool. 51 IsConnWasIdle bool 52 53 // ConnIdleTime is a duration how long the connection was previously 54 // idle, if IsConnWasIdle is true. 55 ConnIdleTime time.Duration 56 57 // RequestAttempt is to represent the request attempt made during a Resty 58 // request execution flow, including retry count. 59 RequestAttempt int 60 61 // RemoteAddr returns the remote network address. 62 RemoteAddr net.Addr 63 } 64 65 //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ 66 // ClientTrace struct and its methods 67 //_______________________________________________________________________ 68 69 // tracer struct maps the `httptrace.ClientTrace` hooks into Fields 70 // with same naming for easy understanding. Plus additional insights 71 // Request. 72 type clientTrace struct { 73 getConn time.Time 74 dnsStart time.Time 75 dnsDone time.Time 76 connectDone time.Time 77 tlsHandshakeStart time.Time 78 tlsHandshakeDone time.Time 79 gotConn time.Time 80 gotFirstResponseByte time.Time 81 endTime time.Time 82 gotConnInfo httptrace.GotConnInfo 83 } 84 85 //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ 86 // Trace unexported methods 87 //_______________________________________________________________________ 88 89 func (t *clientTrace) createContext(ctx context.Context) context.Context { 90 return httptrace.WithClientTrace( 91 ctx, 92 &httptrace.ClientTrace{ 93 DNSStart: func(_ httptrace.DNSStartInfo) { 94 t.dnsStart = time.Now() 95 }, 96 DNSDone: func(_ httptrace.DNSDoneInfo) { 97 t.dnsDone = time.Now() 98 }, 99 ConnectStart: func(_, _ string) { 100 if t.dnsDone.IsZero() { 101 t.dnsDone = time.Now() 102 } 103 if t.dnsStart.IsZero() { 104 t.dnsStart = t.dnsDone 105 } 106 }, 107 ConnectDone: func(net, addr string, err error) { 108 t.connectDone = time.Now() 109 }, 110 GetConn: func(_ string) { 111 t.getConn = time.Now() 112 }, 113 GotConn: func(ci httptrace.GotConnInfo) { 114 t.gotConn = time.Now() 115 t.gotConnInfo = ci 116 }, 117 GotFirstResponseByte: func() { 118 t.gotFirstResponseByte = time.Now() 119 }, 120 TLSHandshakeStart: func() { 121 t.tlsHandshakeStart = time.Now() 122 }, 123 TLSHandshakeDone: func(_ tls.ConnectionState, _ error) { 124 t.tlsHandshakeDone = time.Now() 125 }, 126 }, 127 ) 128 }