github.com/gogf/gf@v1.16.9/net/ghttp/internal/client/client_tracing_tracer.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 client 8 9 import ( 10 "context" 11 "crypto/tls" 12 "fmt" 13 "io/ioutil" 14 "net/http" 15 "net/http/httptrace" 16 "net/textproto" 17 "strings" 18 "sync" 19 20 "github.com/gogf/gf/internal/utils" 21 "github.com/gogf/gf/net/gtrace" 22 "github.com/gogf/gf/text/gstr" 23 "github.com/gogf/gf/util/gconv" 24 "go.opentelemetry.io/otel/attribute" 25 "go.opentelemetry.io/otel/codes" 26 "go.opentelemetry.io/otel/trace" 27 ) 28 29 type clientTracer struct { 30 context.Context 31 span trace.Span 32 request *http.Request 33 requestBody []byte 34 headers map[string]interface{} 35 mtx sync.Mutex 36 } 37 38 func newClientTrace(ctx context.Context, span trace.Span, request *http.Request) *httptrace.ClientTrace { 39 ct := &clientTracer{ 40 Context: ctx, 41 span: span, 42 request: request, 43 headers: make(map[string]interface{}), 44 } 45 46 reqBodyContent, _ := ioutil.ReadAll(ct.request.Body) 47 ct.requestBody = reqBodyContent 48 ct.request.Body = utils.NewReadCloser(reqBodyContent, false) 49 50 return &httptrace.ClientTrace{ 51 GetConn: ct.getConn, 52 GotConn: ct.gotConn, 53 PutIdleConn: ct.putIdleConn, 54 GotFirstResponseByte: ct.gotFirstResponseByte, 55 Got100Continue: ct.got100Continue, 56 Got1xxResponse: ct.got1xxResponse, 57 DNSStart: ct.dnsStart, 58 DNSDone: ct.dnsDone, 59 ConnectStart: ct.connectStart, 60 ConnectDone: ct.connectDone, 61 TLSHandshakeStart: ct.tlsHandshakeStart, 62 TLSHandshakeDone: ct.tlsHandshakeDone, 63 WroteHeaderField: ct.wroteHeaderField, 64 WroteHeaders: ct.wroteHeaders, 65 Wait100Continue: ct.wait100Continue, 66 WroteRequest: ct.wroteRequest, 67 } 68 } 69 70 func (ct *clientTracer) getConn(host string) { 71 72 } 73 74 func (ct *clientTracer) gotConn(info httptrace.GotConnInfo) { 75 ct.span.SetAttributes( 76 attribute.String(tracingAttrHttpAddressRemote, info.Conn.RemoteAddr().String()), 77 attribute.String(tracingAttrHttpAddressLocal, info.Conn.LocalAddr().String()), 78 ) 79 } 80 81 func (ct *clientTracer) putIdleConn(err error) { 82 if err != nil { 83 ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, err)) 84 } 85 } 86 87 func (ct *clientTracer) dnsStart(info httptrace.DNSStartInfo) { 88 ct.span.SetAttributes( 89 attribute.String(tracingAttrHttpDnsStart, info.Host), 90 ) 91 } 92 93 func (ct *clientTracer) dnsDone(info httptrace.DNSDoneInfo) { 94 var buffer strings.Builder 95 for _, v := range info.Addrs { 96 if buffer.Len() != 0 { 97 buffer.WriteString(",") 98 } 99 buffer.WriteString(v.String()) 100 } 101 if info.Err != nil { 102 ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, info.Err)) 103 } 104 ct.span.SetAttributes( 105 attribute.String(tracingAttrHttpDnsDone, buffer.String()), 106 ) 107 } 108 109 func (ct *clientTracer) connectStart(network, addr string) { 110 ct.span.SetAttributes( 111 attribute.String(tracingAttrHttpConnectStart, network+"@"+addr), 112 ) 113 } 114 115 func (ct *clientTracer) connectDone(network, addr string, err error) { 116 if err != nil { 117 ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, err)) 118 } 119 ct.span.SetAttributes( 120 attribute.String(tracingAttrHttpConnectDone, network+"@"+addr), 121 ) 122 } 123 124 func (ct *clientTracer) tlsHandshakeStart() { 125 126 } 127 128 func (ct *clientTracer) tlsHandshakeDone(_ tls.ConnectionState, err error) { 129 if err != nil { 130 ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, err)) 131 } 132 } 133 134 func (ct *clientTracer) wroteHeaderField(k string, v []string) { 135 if len(v) > 1 { 136 ct.headers[k] = v 137 } else { 138 ct.headers[k] = v[0] 139 } 140 } 141 142 func (ct *clientTracer) wroteHeaders() { 143 144 } 145 146 func (ct *clientTracer) wroteRequest(info httptrace.WroteRequestInfo) { 147 if info.Err != nil { 148 ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, info.Err)) 149 } 150 151 ct.span.AddEvent(tracingEventHttpRequest, trace.WithAttributes( 152 attribute.String(tracingEventHttpRequestHeaders, gconv.String(ct.headers)), 153 attribute.String(tracingEventHttpRequestBaggage, gtrace.GetBaggageMap(ct.Context).String()), 154 attribute.String(tracingEventHttpRequestBody, gstr.StrLimit( 155 string(ct.requestBody), 156 gtrace.MaxContentLogSize(), 157 "...", 158 )), 159 )) 160 } 161 162 func (ct *clientTracer) got100Continue() { 163 164 } 165 166 func (ct *clientTracer) wait100Continue() { 167 168 } 169 170 func (ct *clientTracer) gotFirstResponseByte() { 171 172 } 173 174 func (ct *clientTracer) got1xxResponse(code int, header textproto.MIMEHeader) error { 175 return nil 176 }