Browse Source

rest otel support (#943)

zhoushuguang 3 năm trước cách đây
mục cha
commit
280e837c9e

+ 11 - 0
core/opentelemetry/agent.go

@@ -5,6 +5,7 @@ import (
 
 	"github.com/tal-tech/go-zero/core/logx"
 	"github.com/tal-tech/go-zero/core/syncx"
+
 	"go.opentelemetry.io/otel"
 	"go.opentelemetry.io/otel/exporters/jaeger"
 	"go.opentelemetry.io/otel/propagation"
@@ -53,7 +54,17 @@ func StartAgent(c Config) {
 
 		otel.SetTracerProvider(tp)
 		otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
+		otel.SetErrorHandler(otelErrHandler{})
 
 		enabled.Set(true)
 	})
 }
+
+// errHandler handing otel errors.
+type otelErrHandler struct{}
+
+var _ otel.ErrorHandler = otelErrHandler{}
+
+func (o otelErrHandler) Handle(err error) {
+	logx.Errorf("[otel] error: %v", err)
+}

+ 1 - 3
core/opentelemetry/config.go

@@ -1,8 +1,6 @@
 package opentelemetry
 
-const (
-	TraceName = "go-zero"
-)
+const TraceName = "go-zero"
 
 // A Config is a opentelemetry config.
 type Config struct {

+ 3 - 0
core/service/serviceconf.go

@@ -45,6 +45,9 @@ func (sc ServiceConf) SetUp() error {
 	if len(sc.Log.ServiceName) == 0 {
 		sc.Log.ServiceName = sc.Name
 	}
+	if len(sc.OpenTelemetry.Name) == 0 {
+		sc.OpenTelemetry.Name = sc.Name
+	}
 	if err := logx.SetUp(sc.Log); err != nil {
 		return err
 	}

+ 1 - 0
rest/engine.go

@@ -108,6 +108,7 @@ func (s *engine) bindRoute(fr featuredRoutes, router httpx.Router, metrics *stat
 	route Route, verifier func(chain alice.Chain) alice.Chain) error {
 	chain := alice.New(
 		handler.TracingHandler,
+		handler.OtelHandler(route.Path),
 		s.getLogHandler(),
 		handler.PrometheusHandler(route.Path),
 		handler.MaxConns(s.conf.MaxConns),

+ 36 - 0
rest/handler/otelhandler.go

@@ -0,0 +1,36 @@
+package handler
+
+import (
+	"net/http"
+
+	"github.com/tal-tech/go-zero/core/opentelemetry"
+
+	"go.opentelemetry.io/otel"
+	"go.opentelemetry.io/otel/propagation"
+	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
+	oteltrace "go.opentelemetry.io/otel/trace"
+)
+
+func OtelHandler(path string) func(http.Handler) http.Handler {
+	return func(next http.Handler) http.Handler {
+		if !opentelemetry.Enabled() {
+			return next
+		}
+
+		propagator := otel.GetTextMapPropagator()
+		tracer := otel.GetTracerProvider().Tracer(opentelemetry.TraceName)
+
+		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			ctx := propagator.Extract(r.Context(), propagation.HeaderCarrier(r.Header))
+			spanCtx, span := tracer.Start(
+				ctx,
+				path,
+				oteltrace.WithSpanKind(oteltrace.SpanKindServer),
+				oteltrace.WithAttributes(semconv.HTTPServerAttributesFromHTTPRequest("", path, r)...),
+			)
+			defer span.End()
+
+			next.ServeHTTP(w, r.WithContext(spanCtx))
+		})
+	}
+}

+ 49 - 0
rest/handler/otelhandler_test.go

@@ -0,0 +1,49 @@
+package handler
+
+import (
+	"context"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/tal-tech/go-zero/core/opentelemetry"
+	"go.opentelemetry.io/otel/propagation"
+
+	"go.opentelemetry.io/otel"
+	"go.opentelemetry.io/otel/trace"
+)
+
+func TestOtelHandler(t *testing.T) {
+	opentelemetry.StartAgent(opentelemetry.Config{
+		Name:     "go-zero-test",
+		Endpoint: "http://localhost:14268/api/traces",
+		Batcher:  "jaeger",
+		Sampler:  1.0,
+	})
+
+	ts := httptest.NewServer(
+		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			ctx := otel.GetTextMapPropagator().Extract(r.Context(), propagation.HeaderCarrier(r.Header))
+			spanCtx := trace.SpanContextFromContext(ctx)
+			assert.Equal(t, true, spanCtx.IsValid())
+		}),
+	)
+	defer ts.Close()
+
+	client := ts.Client()
+	err := func(ctx context.Context) error {
+		ctx, span := otel.Tracer("httptrace/client").Start(ctx, "test")
+		defer span.End()
+
+		req, _ := http.NewRequest("GET", ts.URL, nil)
+		otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
+
+		res, err := client.Do(req)
+		assert.Equal(t, err, nil)
+		_ = res.Body.Close()
+		return nil
+	}(context.Background())
+
+	assert.Equal(t, err, nil)
+}

+ 1 - 0
zrpc/internal/clientinterceptors/opentracinginterceptor.go

@@ -4,6 +4,7 @@ import (
 	"context"
 
 	"github.com/tal-tech/go-zero/core/opentelemetry"
+
 	"go.opentelemetry.io/otel"
 	"go.opentelemetry.io/otel/codes"
 	"go.opentelemetry.io/otel/trace"

+ 1 - 0
zrpc/internal/serverinterceptors/opentracinginterceptor.go

@@ -4,6 +4,7 @@ import (
 	"context"
 
 	"github.com/tal-tech/go-zero/core/opentelemetry"
+
 	"go.opentelemetry.io/otel"
 	"go.opentelemetry.io/otel/baggage"
 	"go.opentelemetry.io/otel/codes"