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 }