github.com/gogf/gf/v2@v2.7.4/net/gclient/gclient_tracer_metrics.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gclient
     8  
     9  import (
    10  	"crypto/tls"
    11  	"net/http"
    12  	"net/http/httptrace"
    13  	"net/textproto"
    14  
    15  	"github.com/gogf/gf/v2/os/gtime"
    16  )
    17  
    18  type clientTracerMetrics struct {
    19  	*httptrace.ClientTrace
    20  	Request          *http.Request
    21  	ConnectStartTime *gtime.Time
    22  }
    23  
    24  // newClientTracerMetrics creates and returns object of httptrace.ClientTrace.
    25  func newClientTracerMetrics(request *http.Request, baseClientTracer *httptrace.ClientTrace) *httptrace.ClientTrace {
    26  	c := &clientTracerMetrics{
    27  		Request:     request,
    28  		ClientTrace: baseClientTracer,
    29  	}
    30  	return &httptrace.ClientTrace{
    31  		GetConn:              c.GetConn,
    32  		GotConn:              c.GotConn,
    33  		PutIdleConn:          c.PutIdleConn,
    34  		GotFirstResponseByte: c.GotFirstResponseByte,
    35  		Got100Continue:       c.Got100Continue,
    36  		Got1xxResponse:       c.Got1xxResponse,
    37  		DNSStart:             c.DNSStart,
    38  		DNSDone:              c.DNSDone,
    39  		ConnectStart:         c.ConnectStart,
    40  		ConnectDone:          c.ConnectDone,
    41  		TLSHandshakeStart:    c.TLSHandshakeStart,
    42  		TLSHandshakeDone:     c.TLSHandshakeDone,
    43  		WroteHeaderField:     c.WroteHeaderField,
    44  		WroteHeaders:         c.WroteHeaders,
    45  		Wait100Continue:      c.Wait100Continue,
    46  		WroteRequest:         c.WroteRequest,
    47  	}
    48  }
    49  
    50  // GetConn is called before a connection is created or
    51  // retrieved from an idle pool. The hostPort is the
    52  // "host:port" of the target or proxy. GetConn is called even
    53  // if there's already an idle cached connection available.
    54  func (ct *clientTracerMetrics) GetConn(hostPort string) {
    55  	ct.ClientTrace.GetConn(hostPort)
    56  }
    57  
    58  // GotConn is called after a successful connection is
    59  // obtained. There is no hook for failure to obtain a
    60  // connection; instead, use the error from
    61  // Transport.RoundTrip.
    62  func (ct *clientTracerMetrics) GotConn(info httptrace.GotConnInfo) {
    63  	ct.ClientTrace.GotConn(info)
    64  }
    65  
    66  // PutIdleConn is called when the connection is returned to
    67  // the idle pool. If err is nil, the connection was
    68  // successfully returned to the idle pool. If err is non-nil,
    69  // it describes why not. PutIdleConn is not called if
    70  // connection reuse is disabled via Transport.DisableKeepAlives.
    71  // PutIdleConn is called before the caller's Response.Body.Close
    72  // call returns.
    73  // For HTTP/2, this hook is not currently used.
    74  func (ct *clientTracerMetrics) PutIdleConn(err error) {
    75  	ct.ClientTrace.PutIdleConn(err)
    76  }
    77  
    78  // GotFirstResponseByte is called when the first byte of the response
    79  // headers is available.
    80  func (ct *clientTracerMetrics) GotFirstResponseByte() {
    81  	ct.ClientTrace.GotFirstResponseByte()
    82  }
    83  
    84  // Got100Continue is called if the server replies with a "100
    85  // Continue" response.
    86  func (ct *clientTracerMetrics) Got100Continue() {
    87  	ct.ClientTrace.Got100Continue()
    88  }
    89  
    90  // Got1xxResponse is called for each 1xx informational response header
    91  // returned before the final non-1xx response. Got1xxResponse is called
    92  // for "100 Continue" responses, even if Got100Continue is also defined.
    93  // If it returns an error, the client request is aborted with that error value.
    94  func (ct *clientTracerMetrics) Got1xxResponse(code int, header textproto.MIMEHeader) error {
    95  	return ct.ClientTrace.Got1xxResponse(code, header)
    96  }
    97  
    98  // DNSStart is called when a DNS lookup begins.
    99  func (ct *clientTracerMetrics) DNSStart(info httptrace.DNSStartInfo) {
   100  	ct.ClientTrace.DNSStart(info)
   101  }
   102  
   103  // DNSDone is called when a DNS lookup ends.
   104  func (ct *clientTracerMetrics) DNSDone(info httptrace.DNSDoneInfo) {
   105  	ct.ClientTrace.DNSDone(info)
   106  }
   107  
   108  // ConnectStart is called when a new connection's Dial begins.
   109  // If net.Dialer.DualStack (IPv6 "Happy Eyeballs") support is
   110  // enabled, this may be called multiple times.
   111  func (ct *clientTracerMetrics) ConnectStart(network, addr string) {
   112  	if ct.Request.RemoteAddr == "" {
   113  		ct.Request.RemoteAddr = addr
   114  	}
   115  	ct.ConnectStartTime = gtime.Now()
   116  	ct.ClientTrace.ConnectStart(network, addr)
   117  }
   118  
   119  // ConnectDone is called when a new connection's Dial
   120  // completes. The provided err indicates whether the
   121  // connection completed successfully.
   122  // If net.Dialer.DualStack ("Happy Eyeballs") support is
   123  // enabled, this may be called multiple times.
   124  func (ct *clientTracerMetrics) ConnectDone(network, addr string, err error) {
   125  	var (
   126  		duration       = float64(gtime.Now().Sub(ct.ConnectStartTime).Milliseconds())
   127  		durationOption = metricManager.GetMetricOptionForHistogram(ct.Request)
   128  	)
   129  	metricManager.HttpClientConnectionDuration.Record(
   130  		duration,
   131  		durationOption,
   132  	)
   133  	ct.ClientTrace.ConnectDone(network, addr, err)
   134  }
   135  
   136  // TLSHandshakeStart is called when the TLS handshake is started. When
   137  // connecting to an HTTPS site via an HTTP proxy, the handshake happens
   138  // after the CONNECT request is processed by the proxy.
   139  func (ct *clientTracerMetrics) TLSHandshakeStart() {
   140  	ct.ClientTrace.TLSHandshakeStart()
   141  }
   142  
   143  // TLSHandshakeDone is called after the TLS handshake with either the
   144  // successful handshake's connection state, or a non-nil error on handshake
   145  // failure.
   146  func (ct *clientTracerMetrics) TLSHandshakeDone(state tls.ConnectionState, err error) {
   147  	ct.ClientTrace.TLSHandshakeDone(state, err)
   148  }
   149  
   150  // WroteHeaderField is called after the Transport has written
   151  // each request header. At the time of this call the values
   152  // might be buffered and not yet written to the network.
   153  func (ct *clientTracerMetrics) WroteHeaderField(key string, value []string) {
   154  	ct.ClientTrace.WroteHeaderField(key, value)
   155  }
   156  
   157  // WroteHeaders is called after the Transport has written
   158  // all request headers.
   159  func (ct *clientTracerMetrics) WroteHeaders() {
   160  	ct.ClientTrace.WroteHeaders()
   161  }
   162  
   163  // Wait100Continue is called if the Request specified
   164  // "Expect: 100-continue" and the Transport has written the
   165  // request headers but is waiting for "100 Continue" from the
   166  // server before writing the request body.
   167  func (ct *clientTracerMetrics) Wait100Continue() {
   168  	ct.ClientTrace.Wait100Continue()
   169  }
   170  
   171  // WroteRequest is called with the result of writing the
   172  // request and any body. It may be called multiple times
   173  // in the case of retried requests.
   174  func (ct *clientTracerMetrics) WroteRequest(info httptrace.WroteRequestInfo) {
   175  	ct.ClientTrace.WroteRequest(info)
   176  }