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  }