4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							| @@ -3,9 +3,9 @@ module go.unistack.org/micro-tracer-instana/v3 | ||||
| go 1.20 | ||||
|  | ||||
| require ( | ||||
| 	github.com/instana/go-sensor v1.55.2 | ||||
| 	github.com/instana/go-sensor v1.60.0 | ||||
| 	github.com/opentracing/opentracing-go v1.2.0 | ||||
| 	go.unistack.org/micro/v3 v3.10.25 | ||||
| 	go.unistack.org/micro/v3 v3.10.50 | ||||
| ) | ||||
|  | ||||
| require ( | ||||
|   | ||||
							
								
								
									
										8
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.sum
									
									
									
									
									
								
							| @@ -1,8 +1,8 @@ | ||||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/instana/go-sensor v1.55.2 h1:XdLN38mSFsHpaL+jIDkE/ZrW7pxgPeUC/bV9bSwVHyM= | ||||
| github.com/instana/go-sensor v1.55.2/go.mod h1:Ks06EG9Da5O3hbdJiHIePG/vNmToovkaJjMlUBd70Yc= | ||||
| github.com/instana/go-sensor v1.60.0 h1:lsAiwmK5AtNQ9gLHPLvZt0aLddZxM4R0oakkO7rXO2U= | ||||
| github.com/instana/go-sensor v1.60.0/go.mod h1:Ks06EG9Da5O3hbdJiHIePG/vNmToovkaJjMlUBd70Yc= | ||||
| github.com/looplab/fsm v1.0.1 h1:OEW0ORrIx095N/6lgoGkFkotqH6s7vaFPsgjLAaF5QU= | ||||
| github.com/looplab/fsm v1.0.1/go.mod h1:PmD3fFvQEIsjMEfvZdrCDZ6y8VwKTwWNjlpEr6IKPO4= | ||||
| github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= | ||||
| @@ -18,8 +18,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO | ||||
| github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | ||||
| github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= | ||||
| github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||||
| go.unistack.org/micro/v3 v3.10.25 h1:A0epdZHOqjnXx103wwFhPKgmvVVbScvfbmn3HmHz1wE= | ||||
| go.unistack.org/micro/v3 v3.10.25/go.mod h1:ALkeXpqChYDjx8KPi7tz9mmIyOnob6nlNswsg8BnZjQ= | ||||
| go.unistack.org/micro/v3 v3.10.50 h1:U0aYtKHrpGHFDYdTRgsIYxIejU4HKDKbLHcLZngvDIs= | ||||
| go.unistack.org/micro/v3 v3.10.50/go.mod h1:erMgt3Bl7vQQ0e9UpQyR5NlLiZ9pKeEJ9+1tfYFaqUg= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||
|   | ||||
							
								
								
									
										148
									
								
								instana.go
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								instana.go
									
									
									
									
									
								
							| @@ -2,60 +2,106 @@ package instana | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
|  | ||||
| 	instana "github.com/instana/go-sensor" | ||||
| 	sensor "github.com/instana/go-sensor" | ||||
| 	"github.com/opentracing/opentracing-go" | ||||
| 	"github.com/opentracing/opentracing-go/log" | ||||
| 	"go.unistack.org/micro/v3/metadata" | ||||
| 	"go.unistack.org/micro/v3/tracer" | ||||
| 	rutil "go.unistack.org/micro/v3/util/reflect" | ||||
| ) | ||||
|  | ||||
| var _ tracer.Tracer = &Tracer{} | ||||
| var _ tracer.Tracer = (*Tracer)(nil) | ||||
|  | ||||
| type Tracer struct { | ||||
| 	opts   tracer.Options | ||||
| 	sensor sensor.Tracer | ||||
| } | ||||
|  | ||||
| func (ot *Tracer) Name() string { | ||||
| 	return ot.opts.Name | ||||
| func (t *Tracer) Name() string { | ||||
| 	return t.opts.Name | ||||
| } | ||||
|  | ||||
| func (ot *Tracer) Flush(ctx context.Context) error { | ||||
| func (t *Tracer) Flush(ctx context.Context) error { | ||||
| 	sensor.ShutdownSensor() | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (ot *Tracer) Init(opts ...tracer.Option) error { | ||||
| func (t *Tracer) Init(opts ...tracer.Option) error { | ||||
| 	for _, o := range opts { | ||||
| 		o(&ot.opts) | ||||
| 		o(&t.opts) | ||||
| 	} | ||||
|  | ||||
| 	sensorOptions := sensor.DefaultOptions() | ||||
| 	if v, ok := ot.opts.Context.Value(tracerOptionsKey{}).(*sensor.Options); ok && v != nil { | ||||
| 	if v, ok := t.opts.Context.Value(tracerOptionsKey{}).(*sensor.Options); ok && v != nil { | ||||
| 		sensorOptions = v | ||||
| 	} | ||||
|  | ||||
| 	ot.sensor = sensor.NewSensorWithTracer(sensor.NewTracerWithOptions(sensorOptions)) | ||||
| 	if sensorOptions.Service == "" { | ||||
| 		sensorOptions.Service = "micro" | ||||
| 	} | ||||
|  | ||||
| 	var recorder instana.SpanRecorder | ||||
| 	recorder = &sensor.Recorder{} | ||||
| 	if v, ok := t.opts.Context.Value(recorderKey{}).(sensor.SpanRecorder); ok && v != nil { | ||||
| 		recorder = v | ||||
| 	} | ||||
|  | ||||
| 	t.sensor = sensor.NewSensorWithTracer(sensor.NewTracerWithEverything(sensorOptions, recorder)) | ||||
|  | ||||
| 	sensor.StartMetrics(sensorOptions) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (ot *Tracer) Start(ctx context.Context, name string, opts ...tracer.SpanOption) (context.Context, tracer.Span) { | ||||
| type idStringer struct { | ||||
| 	s string | ||||
| } | ||||
|  | ||||
| func (s idStringer) String() string { | ||||
| 	return s.s | ||||
| } | ||||
|  | ||||
| type spanContext interface { | ||||
| 	TraceID() idStringer | ||||
| 	SpanID() idStringer | ||||
| } | ||||
|  | ||||
| func (t *Tracer) Start(ctx context.Context, name string, opts ...tracer.SpanOption) (context.Context, tracer.Span) { | ||||
| 	options := tracer.NewSpanOptions(opts...) | ||||
| 	var span opentracing.Span | ||||
| 	switch options.Kind { | ||||
| 	case tracer.SpanKindInternal, tracer.SpanKindUnspecified: | ||||
| 		ctx, span = ot.startSpanFromContext(ctx, name) | ||||
| 		ctx, span = t.startSpanFromContext(ctx, name) | ||||
| 	case tracer.SpanKindClient, tracer.SpanKindProducer: | ||||
| 		ctx, span = ot.startSpanFromOutgoingContext(ctx, name) | ||||
| 		ctx, span = t.startSpanFromOutgoingContext(ctx, name) | ||||
| 	case tracer.SpanKindServer, tracer.SpanKindConsumer: | ||||
| 		ctx, span = ot.startSpanFromIncomingContext(ctx, name) | ||||
| 		ctx, span = t.startSpanFromIncomingContext(ctx, name) | ||||
| 	} | ||||
| 	return ctx, &otSpan{span: span, opts: options} | ||||
|  | ||||
| 	sp := &otSpan{topts: t.opts, span: span, opts: options, sensor: t.sensor, status: tracer.SpanStatusOK} | ||||
|  | ||||
| 	spctx := span.Context() | ||||
| 	if v, ok := spctx.(spanContext); ok { | ||||
| 		sp.traceID = v.TraceID().String() | ||||
| 		sp.spanID = v.SpanID().String() | ||||
| 	} else { | ||||
| 		if val, err := rutil.StructFieldByName(spctx, "TraceID"); err == nil { | ||||
| 			sp.traceID = fmt.Sprintf("%v", val) | ||||
| 		} | ||||
| 		if val, err := rutil.StructFieldByName(spctx, "SpanID"); err == nil { | ||||
| 			sp.spanID = fmt.Sprintf("%v", val) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return ctx, sp | ||||
| } | ||||
|  | ||||
| type otSpan struct { | ||||
| 	span      opentracing.Span | ||||
| 	spanID    string | ||||
| 	traceID   string | ||||
| 	sensor    sensor.Tracer | ||||
| 	topts     tracer.Options | ||||
| 	opts      tracer.SpanOptions | ||||
| @@ -63,6 +109,14 @@ type otSpan struct { | ||||
| 	statusMsg string | ||||
| } | ||||
|  | ||||
| func (os *otSpan) TraceID() string { | ||||
| 	return os.traceID | ||||
| } | ||||
|  | ||||
| func (os *otSpan) SpanID() string { | ||||
| 	return os.spanID | ||||
| } | ||||
|  | ||||
| func (os *otSpan) SetStatus(st tracer.SpanStatus, msg string) { | ||||
| 	switch st { | ||||
| 	case tracer.SpanStatusError: | ||||
| @@ -80,10 +134,37 @@ func (os *otSpan) Tracer() tracer.Tracer { | ||||
| 	return &Tracer{sensor: os.sensor, opts: os.topts} | ||||
| } | ||||
|  | ||||
| func (os *otSpan) AddLogs(kv ...interface{}) { | ||||
| 	os.span.LogKV(kv...) | ||||
| } | ||||
|  | ||||
| func (os *otSpan) Finish(opts ...tracer.SpanOption) { | ||||
| 	if len(os.opts.Labels) > 0 { | ||||
| 		os.span.LogKV(os.opts.Labels...) | ||||
| 	if len(os.opts.Labels)%2 != 0 { | ||||
| 		os.opts.Labels = os.opts.Labels[:len(os.opts.Labels)-1] | ||||
| 	} | ||||
| 	os.opts.Labels = tracer.UniqLabels(os.opts.Labels) | ||||
| 	for idx := 0; idx < len(os.opts.Labels); idx += 2 { | ||||
| 		switch os.opts.Labels[idx] { | ||||
| 		case "err": | ||||
| 			os.status = tracer.SpanStatusError | ||||
| 			os.statusMsg = fmt.Sprintf("%v", os.opts.Labels[idx+1]) | ||||
| 		case "error": | ||||
| 			continue | ||||
| 		case "X-Request-Id", "x-request-id": | ||||
| 			os.span.SetTag("x-request-id", os.opts.Labels[idx+1]) | ||||
| 		case "rpc.call", "rpc.call_type", "rpc.flavor", "rpc.service", "rpc.method", | ||||
| 			"sdk.database", "db.statement", "db.args", "db.query", "db.method", | ||||
| 			"messaging.destination.name", "messaging.source.name", "messaging.operation": | ||||
| 			os.span.SetTag(fmt.Sprintf("%v", os.opts.Labels[idx]), os.opts.Labels[idx+1]) | ||||
| 		default: | ||||
| 			os.span.LogKV(os.opts.Labels[idx], os.opts.Labels[idx+1]) | ||||
| 		} | ||||
| 	} | ||||
| 	if os.status == tracer.SpanStatusError { | ||||
| 		os.span.SetTag("error", true) | ||||
| 		os.span.LogKV("error", os.statusMsg) | ||||
| 	} | ||||
| 	os.span.SetTag("span.kind", os.opts.Kind) | ||||
| 	os.span.Finish() | ||||
| } | ||||
|  | ||||
| @@ -120,14 +201,34 @@ func spanFromContext(ctx context.Context) (opentracing.Span, bool) { | ||||
| 	return sensor.SpanFromContext(ctx) | ||||
| } | ||||
|  | ||||
| func (ot *Tracer) startSpanFromContext(ctx context.Context, name string, opts ...opentracing.StartSpanOption) (context.Context, opentracing.Span) { | ||||
| func (t *Tracer) startSpanFromAny(ctx context.Context, name string, opts ...opentracing.StartSpanOption) (context.Context, opentracing.Span) { | ||||
| 	if tracerSpan, ok := tracer.SpanFromContext(ctx); ok && tracerSpan != nil { | ||||
| 		return t.startSpanFromContext(ctx, name, opts...) | ||||
| 	} | ||||
|  | ||||
| 	if otSpan := opentracing.SpanFromContext(ctx); otSpan != nil { | ||||
| 		return t.startSpanFromContext(ctx, name, opts...) | ||||
| 	} | ||||
|  | ||||
| 	if md, ok := metadata.FromIncomingContext(ctx); ok && md != nil { | ||||
| 		return t.startSpanFromIncomingContext(ctx, name, opts...) | ||||
| 	} | ||||
|  | ||||
| 	if md, ok := metadata.FromOutgoingContext(ctx); ok && md != nil { | ||||
| 		return t.startSpanFromOutgoingContext(ctx, name, opts...) | ||||
| 	} | ||||
|  | ||||
| 	return t.startSpanFromContext(ctx, name, opts...) | ||||
| } | ||||
|  | ||||
| func (t *Tracer) startSpanFromContext(ctx context.Context, name string, opts ...opentracing.StartSpanOption) (context.Context, opentracing.Span) { | ||||
| 	if parentSpan := opentracing.SpanFromContext(ctx); parentSpan != nil { | ||||
| 		opts = append(opts, opentracing.ChildOf(parentSpan.Context())) | ||||
| 	} | ||||
|  | ||||
| 	md := metadata.New(1) | ||||
|  | ||||
| 	sp := ot.sensor.StartSpan(name, opts...) | ||||
| 	sp := t.sensor.StartSpan(name, opts...) | ||||
| 	if err := sp.Tracer().Inject(sp.Context(), opentracing.TextMap, opentracing.TextMapCarrier(md)); err != nil { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| @@ -137,12 +238,12 @@ func (ot *Tracer) startSpanFromContext(ctx context.Context, name string, opts .. | ||||
| 	return ctx, sp | ||||
| } | ||||
|  | ||||
| func (ot *Tracer) startSpanFromOutgoingContext(ctx context.Context, name string, opts ...opentracing.StartSpanOption) (context.Context, opentracing.Span) { | ||||
| func (t *Tracer) startSpanFromOutgoingContext(ctx context.Context, name string, opts ...opentracing.StartSpanOption) (context.Context, opentracing.Span) { | ||||
| 	var parentCtx opentracing.SpanContext | ||||
|  | ||||
| 	md, ok := metadata.FromOutgoingContext(ctx) | ||||
| 	if ok && md != nil { | ||||
| 		if spanCtx, err := ot.sensor.Extract(opentracing.TextMap, opentracing.TextMapCarrier(md)); err == nil && ok { | ||||
| 		if spanCtx, err := t.sensor.Extract(opentracing.TextMap, opentracing.TextMapCarrier(md)); err == nil && ok { | ||||
| 			parentCtx = spanCtx | ||||
| 		} | ||||
| 	} | ||||
| @@ -153,7 +254,7 @@ func (ot *Tracer) startSpanFromOutgoingContext(ctx context.Context, name string, | ||||
|  | ||||
| 	nmd := metadata.Copy(md) | ||||
|  | ||||
| 	sp := ot.sensor.StartSpan(name, opts...) | ||||
| 	sp := t.sensor.StartSpan(name, opts...) | ||||
| 	if err := sp.Tracer().Inject(sp.Context(), opentracing.TextMap, opentracing.TextMapCarrier(nmd)); err != nil { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| @@ -163,12 +264,12 @@ func (ot *Tracer) startSpanFromOutgoingContext(ctx context.Context, name string, | ||||
| 	return ctx, sp | ||||
| } | ||||
|  | ||||
| func (ot *Tracer) startSpanFromIncomingContext(ctx context.Context, name string, opts ...opentracing.StartSpanOption) (context.Context, opentracing.Span) { | ||||
| func (t *Tracer) startSpanFromIncomingContext(ctx context.Context, name string, opts ...opentracing.StartSpanOption) (context.Context, opentracing.Span) { | ||||
| 	var parentCtx opentracing.SpanContext | ||||
|  | ||||
| 	md, ok := metadata.FromIncomingContext(ctx) | ||||
| 	if ok && md != nil { | ||||
| 		if spanCtx, err := ot.sensor.Extract(opentracing.TextMap, opentracing.TextMapCarrier(md)); err == nil { | ||||
| 		if spanCtx, err := t.sensor.Extract(opentracing.TextMap, opentracing.TextMapCarrier(md)); err == nil { | ||||
| 			parentCtx = spanCtx | ||||
| 		} | ||||
| 	} | ||||
| @@ -179,7 +280,8 @@ func (ot *Tracer) startSpanFromIncomingContext(ctx context.Context, name string, | ||||
|  | ||||
| 	nmd := metadata.Copy(md) | ||||
|  | ||||
| 	sp := ot.sensor.StartSpan(name, opts...) | ||||
| 	sp := t.sensor.StartSpan(name, opts...) | ||||
| 	// fmt.Printf("StartSpan %#+v\n", sp) | ||||
| 	if err := sp.Tracer().Inject(sp.Context(), opentracing.TextMap, opentracing.TextMapCarrier(nmd)); err != nil { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										59
									
								
								instana_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								instana_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| package instana | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"testing" | ||||
|  | ||||
| 	sensor "github.com/instana/go-sensor" | ||||
| 	"go.unistack.org/micro/v3/metadata" | ||||
| 	"go.unistack.org/micro/v3/tracer" | ||||
| ) | ||||
|  | ||||
| func TestTraceID(t *testing.T) { | ||||
| 	md := metadata.New(1) | ||||
| 	ctx, cancel := context.WithCancel(context.Background()) | ||||
| 	defer cancel() | ||||
| 	ctx = metadata.NewIncomingContext(ctx, md) | ||||
|  | ||||
| 	tr := NewTracer() | ||||
| 	if err := tr.Init(); err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	var sp tracer.Span | ||||
|  | ||||
| 	ctx, sp = tr.Start(ctx, "test") | ||||
| 	if v := sp.TraceID(); v == "" { | ||||
| 		t.Fatalf("invalid span trace id %#+v", v) | ||||
| 	} | ||||
| 	if v := sp.SpanID(); v == "" { | ||||
| 		t.Fatalf("invalid span span id %#+v", v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestSpanPropogation(t *testing.T) { | ||||
| 	md := metadata.New(0) | ||||
| 	md.Set( | ||||
| 		"X-Instana-T", "0000000000002435", | ||||
| 		"X-Instana-S", "0000000000003546", | ||||
| 		"X-Instana-L", "1", | ||||
| 		"Traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000003546-01", | ||||
| 		"Tracestate", "in=0000000000002435;0000000000003546,rojo=00f067aa0ba902b7", | ||||
| 	) | ||||
|  | ||||
| 	ctx := metadata.NewIncomingContext(context.TODO(), md) | ||||
| 	var span tracer.Span | ||||
| 	r := sensor.NewTestRecorder() | ||||
| 	tr := NewTracer(Recorder(r)) | ||||
| 	if err := tr.Init(); err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	ctx, span = tr.Start(ctx, "test", tracer.WithSpanKind(tracer.SpanKindServer)) | ||||
| 	span.Finish() | ||||
|  | ||||
| 	spans := r.GetQueuedSpans() | ||||
| 	for _, s := range spans { | ||||
| 		t.Logf("spans %#+v\n", s) | ||||
| 	} | ||||
| 	tr.Flush(ctx) | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| package instana | ||||
|  | ||||
| import ( | ||||
| 	instana "github.com/instana/go-sensor" | ||||
| 	sensor "github.com/instana/go-sensor" | ||||
| 	"go.unistack.org/micro/v3/tracer" | ||||
| ) | ||||
| @@ -10,3 +11,9 @@ type tracerOptionsKey struct{} | ||||
| func Options(opts *sensor.Options) tracer.Option { | ||||
| 	return tracer.SetOption(tracerOptionsKey{}, opts) | ||||
| } | ||||
|  | ||||
| type recorderKey struct{} | ||||
|  | ||||
| func Recorder(r instana.SpanRecorder) tracer.Option { | ||||
| 	return tracer.SetOption(recorderKey{}, r) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user