From 40bdc76af1914b1a60aa794afb23d2400885ee57 Mon Sep 17 00:00:00 2001 From: jianchenma Date: Wed, 3 Feb 2021 15:14:07 +0800 Subject: [PATCH] improve package gtrace --- net/ghttp/ghttp_middleware_tracing.go | 8 +-- net/ghttp/internal/client/client_tracing.go | 7 +-- net/gtrace/gtrace.go | 11 ++++ net/gtrace/gtrace_carrier.go | 51 +++++++++++++++++ net/gtrace/gtrace_unit_carrier_test.go | 63 +++++++++++++++++++++ 5 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 net/gtrace/gtrace_carrier.go create mode 100644 net/gtrace/gtrace_unit_carrier_test.go diff --git a/net/ghttp/ghttp_middleware_tracing.go b/net/ghttp/ghttp_middleware_tracing.go index 1422e736e..f8b19122b 100644 --- a/net/ghttp/ghttp_middleware_tracing.go +++ b/net/ghttp/ghttp_middleware_tracing.go @@ -16,7 +16,6 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/label" - "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/trace" "io/ioutil" "net/http" @@ -42,12 +41,7 @@ func MiddlewareClientTracing(c *Client, r *http.Request) (*ClientResponse, error // MiddlewareServerTracing is a serer middleware that enables tracing feature using standards of OpenTelemetry. func MiddlewareServerTracing(r *Request) { tr := otel.GetTracerProvider().Tracer(tracingInstrumentName, trace.WithInstrumentationVersion(gf.VERSION)) - // Tracing content parsing, start root span. - propagator := propagation.NewCompositeTextMapPropagator( - propagation.TraceContext{}, - propagation.Baggage{}, - ) - ctx := propagator.Extract(r.Context(), r.Header) + ctx := gtrace.DefaultTextMapPropagator().Extract(r.Context(), r.Header) ctx, span := tr.Start(ctx, r.URL.String(), trace.WithSpanKind(trace.SpanKindServer)) defer span.End() diff --git a/net/ghttp/internal/client/client_tracing.go b/net/ghttp/internal/client/client_tracing.go index 9d034e5ea..5f7e914bb 100644 --- a/net/ghttp/internal/client/client_tracing.go +++ b/net/ghttp/internal/client/client_tracing.go @@ -15,7 +15,6 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/label" - "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/trace" "io/ioutil" "net/http" @@ -49,11 +48,7 @@ func MiddlewareTracing(c *Client, r *http.Request) (response *Response, err erro span.SetAttributes(gtrace.CommonLabels()...) // Inject tracing content into http header. - propagator := propagation.NewCompositeTextMapPropagator( - propagation.TraceContext{}, - propagation.Baggage{}, - ) - propagator.Inject(ctx, r.Header) + gtrace.DefaultTextMapPropagator().Inject(ctx, r.Header) // Continue client handler executing. response, err = c.Next( diff --git a/net/gtrace/gtrace.go b/net/gtrace/gtrace.go index 0ffb82d76..aaa1b3e68 100644 --- a/net/gtrace/gtrace.go +++ b/net/gtrace/gtrace.go @@ -13,6 +13,7 @@ import ( "github.com/gogf/gf/container/gvar" "github.com/gogf/gf/net/gipv4" "go.opentelemetry.io/otel/label" + "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/trace" "os" "strings" @@ -27,6 +28,11 @@ var ( intranetIps, _ = gipv4.GetIntranetIpArray() intranetIpStr = strings.Join(intranetIps, ",") hostname, _ = os.Hostname() + // defaultTextMapPropagator is the default propagator for context propagation between peers. + defaultTextMapPropagator = propagation.NewCompositeTextMapPropagator( + propagation.TraceContext{}, + propagation.Baggage{}, + ) ) // CommonLabels returns common used attribute labels: @@ -43,6 +49,11 @@ func IsActivated(ctx context.Context) bool { return GetTraceId(ctx) != "" } +// DefaultTextMapPropagator returns the default propagator for context propagation between peers. +func DefaultTextMapPropagator() propagation.TextMapPropagator { + return defaultTextMapPropagator +} + // GetTraceId retrieves and returns TraceId from context. // It returns an empty string is tracing feature is not activated. func GetTraceId(ctx context.Context) string { diff --git a/net/gtrace/gtrace_carrier.go b/net/gtrace/gtrace_carrier.go new file mode 100644 index 000000000..6cc55f857 --- /dev/null +++ b/net/gtrace/gtrace_carrier.go @@ -0,0 +1,51 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtrace + +import ( + "github.com/gogf/gf/internal/json" + "github.com/gogf/gf/util/gconv" +) + +type Carrier struct { + data map[string]interface{} +} + +func NewCarrier(data ...map[string]interface{}) *Carrier { + carrier := &Carrier{} + if len(data) > 0 && data[0] != nil { + carrier.data = data[0] + } else { + carrier.data = make(map[string]interface{}) + } + return carrier +} + +func (c *Carrier) Get(k string) string { + return gconv.String(c.data[k]) +} + +func (c *Carrier) Set(k, v string) { + c.data[k] = v +} + +func (c *Carrier) MustMarshal() []byte { + b, err := json.Marshal(c.data) + if err != nil { + panic(err) + } + return b +} + +func (c *Carrier) String() string { + return string(c.MustMarshal()) +} + +func (c *Carrier) UnmarshalJSON(b []byte) error { + carrier := NewCarrier(nil) + return json.Unmarshal(b, carrier.data) +} diff --git a/net/gtrace/gtrace_unit_carrier_test.go b/net/gtrace/gtrace_unit_carrier_test.go new file mode 100644 index 000000000..81080815c --- /dev/null +++ b/net/gtrace/gtrace_unit_carrier_test.go @@ -0,0 +1,63 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtrace_test + +import ( + "context" + "github.com/gogf/gf/net/gtrace" + "github.com/gogf/gf/test/gtest" + "go.opentelemetry.io/otel/oteltest" + "go.opentelemetry.io/otel/trace" + "testing" +) + +const ( + traceIDStr = "4bf92f3577b34da6a3ce929d0e0e4736" + spanIDStr = "00f067aa0ba902b7" +) + +var ( + traceID = mustTraceIDFromHex(traceIDStr) + spanID = mustSpanIDFromHex(spanIDStr) +) + +func mustTraceIDFromHex(s string) (t trace.TraceID) { + var err error + t, err = trace.TraceIDFromHex(s) + if err != nil { + panic(err) + } + return +} + +func mustSpanIDFromHex(s string) (t trace.SpanID) { + var err error + t, err = trace.SpanIDFromHex(s) + if err != nil { + panic(err) + } + return +} + +func TestNewCarrier(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + ctx := trace.ContextWithRemoteSpanContext(context.Background(), trace.SpanContext{ + TraceID: traceID, + SpanID: spanID, + TraceFlags: trace.FlagsSampled, + }) + ctx, _ = oteltest.DefaultTracer().Start(ctx, "inject") + carrier1 := gtrace.NewCarrier() + gtrace.DefaultTextMapPropagator().Inject(ctx, carrier1) + t.Assert(carrier1.String(), `{"traceparent":"00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000000002-01","tracestate":""}`) + + ctx = gtrace.DefaultTextMapPropagator().Extract(ctx, carrier1) + gotSc := trace.RemoteSpanContextFromContext(ctx) + t.Assert(gotSc.TraceID.String(), traceID.String()) + t.Assert(gotSc.SpanID.String(), "0000000000000002") + }) +}