github.com/gogf/gf@v1.16.9/net/ghttp/ghttp_middleware_tracing.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 ghttp 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "net/http" 13 14 "github.com/gogf/gf" 15 "github.com/gogf/gf/internal/utils" 16 "github.com/gogf/gf/net/ghttp/internal/client" 17 "github.com/gogf/gf/net/ghttp/internal/httputil" 18 "github.com/gogf/gf/net/gtrace" 19 "github.com/gogf/gf/text/gstr" 20 "github.com/gogf/gf/util/gconv" 21 "go.opentelemetry.io/otel" 22 "go.opentelemetry.io/otel/attribute" 23 "go.opentelemetry.io/otel/codes" 24 "go.opentelemetry.io/otel/propagation" 25 "go.opentelemetry.io/otel/trace" 26 ) 27 28 const ( 29 tracingInstrumentName = "github.com/gogf/gf/net/ghttp.Server" 30 tracingEventHttpRequest = "http.request" 31 tracingEventHttpRequestHeaders = "http.request.headers" 32 tracingEventHttpRequestBaggage = "http.request.baggage" 33 tracingEventHttpRequestBody = "http.request.body" 34 tracingEventHttpResponse = "http.response" 35 tracingEventHttpResponseHeaders = "http.response.headers" 36 tracingEventHttpResponseBody = "http.response.body" 37 ) 38 39 // MiddlewareClientTracing is a client middleware that enables tracing feature using standards of OpenTelemetry. 40 func MiddlewareClientTracing(c *Client, r *http.Request) (*ClientResponse, error) { 41 return client.MiddlewareTracing(c, r) 42 } 43 44 // MiddlewareServerTracing is a serer middleware that enables tracing feature using standards of OpenTelemetry. 45 func MiddlewareServerTracing(r *Request) { 46 tr := otel.GetTracerProvider().Tracer(tracingInstrumentName, trace.WithInstrumentationVersion(gf.VERSION)) 47 ctx := otel.GetTextMapPropagator().Extract(r.Context(), propagation.HeaderCarrier(r.Header)) 48 ctx, span := tr.Start(ctx, r.URL.String(), trace.WithSpanKind(trace.SpanKindServer)) 49 defer span.End() 50 51 span.SetAttributes(gtrace.CommonLabels()...) 52 53 // Inject tracing context. 54 r.SetCtx(ctx) 55 56 // Request content logging. 57 reqBodyContentBytes, _ := ioutil.ReadAll(r.Body) 58 r.Body = utils.NewReadCloser(reqBodyContentBytes, false) 59 60 span.AddEvent(tracingEventHttpRequest, trace.WithAttributes( 61 attribute.String(tracingEventHttpRequestHeaders, gconv.String(httputil.HeaderToMap(r.Header))), 62 attribute.String(tracingEventHttpRequestBaggage, gtrace.GetBaggageMap(ctx).String()), 63 attribute.String(tracingEventHttpRequestBody, gstr.StrLimit( 64 string(reqBodyContentBytes), 65 gtrace.MaxContentLogSize(), 66 "...", 67 )), 68 )) 69 70 // Continue executing. 71 r.Middleware.Next() 72 73 // Error logging. 74 if err := r.GetError(); err != nil { 75 span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, err)) 76 } 77 // Response content logging. 78 var resBodyContent string 79 resBodyContent = r.Response.BufferString() 80 resBodyContent = gstr.StrLimit( 81 r.Response.BufferString(), 82 gtrace.MaxContentLogSize(), 83 "...", 84 ) 85 86 span.AddEvent(tracingEventHttpResponse, trace.WithAttributes( 87 attribute.String(tracingEventHttpResponseHeaders, gconv.String(httputil.HeaderToMap(r.Response.Header()))), 88 attribute.String(tracingEventHttpResponseBody, resBodyContent), 89 )) 90 return 91 }