From da2c2b7d046b4deb51462c85902ec07d74c84f89 Mon Sep 17 00:00:00 2001 From: Pulak Bhowmick Date: Fri, 1 Dec 2023 17:41:33 +0600 Subject: [PATCH 1/6] add tracing option in go-sdk --- go.mod | 4 ++- go.sum | 10 ++++-- pkg/client/client.go | 7 +++++ pkg/client/factory.go | 14 +++++++++ pkg/tracing/opentelemetry.go | 60 ++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 pkg/tracing/opentelemetry.go diff --git a/go.mod b/go.mod index 8ceaaa5a..d3a22b2d 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,10 @@ require ( github.com/json-iterator/go v1.1.12 github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.7.0 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.4 github.com/twmb/murmur3 v1.1.6 + go.opentelemetry.io/otel v1.21.0 + go.opentelemetry.io/otel/trace v1.21.0 golang.org/x/sync v0.1.0 ) diff --git a/go.sum b/go.sum index a733a1c9..0b84da8a 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ 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/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= @@ -37,10 +39,14 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pkg/client/client.go b/pkg/client/client.go index 9093e0e7..65a0f58b 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -18,6 +18,7 @@ package client import ( + "context" "encoding/json" "errors" "fmt" @@ -37,6 +38,7 @@ import ( pkgOdpSegment "github.com/optimizely/go-sdk/pkg/odp/segment" pkgOdpUtils "github.com/optimizely/go-sdk/pkg/odp/utils" "github.com/optimizely/go-sdk/pkg/optimizelyjson" + "github.com/optimizely/go-sdk/pkg/tracing" "github.com/optimizely/go-sdk/pkg/utils" "github.com/hashicorp/go-multierror" @@ -52,6 +54,7 @@ type OptimizelyClient struct { execGroup *utils.ExecGroup logger logging.OptimizelyLogProducer defaultDecideOptions *decide.Options + tracer tracing.Tracer } // CreateUserContext creates a context of the user for which decision APIs will be called. @@ -66,6 +69,10 @@ func (o *OptimizelyClient) CreateUserContext(userID string, attributes map[strin } func (o *OptimizelyClient) decide(userContext OptimizelyUserContext, key string, options *decide.Options) OptimizelyDecision { + // TODO: we need to change userContext to carry a context from the caller to use in StartSpan + _, span := o.tracer.StartSpan(context.TODO(), "decide") + defer span.End() + var err error defer func() { if r := recover(); r != nil { diff --git a/pkg/client/factory.go b/pkg/client/factory.go index b6c7aef1..937aa64b 100644 --- a/pkg/client/factory.go +++ b/pkg/client/factory.go @@ -32,6 +32,7 @@ import ( "github.com/optimizely/go-sdk/pkg/odp" pkgUtils "github.com/optimizely/go-sdk/pkg/odp/utils" "github.com/optimizely/go-sdk/pkg/registry" + "github.com/optimizely/go-sdk/pkg/tracing" "github.com/optimizely/go-sdk/pkg/utils" ) @@ -48,6 +49,7 @@ type OptimizelyFactory struct { eventDispatcher event.Dispatcher eventProcessor event.Processor metricsRegistry metrics.Registry + tracer tracing.Tracer overrideStore decision.ExperimentOverrideStore userProfileService decision.UserProfileService notificationCenter notification.Center @@ -113,6 +115,12 @@ func (f *OptimizelyFactory) Client(clientOptions ...OptionFunc) (*OptimizelyClie appClient.notificationCenter = registry.GetNotificationCenter(f.SDKKey) } + if f.tracer != nil { + appClient.tracer = f.tracer + } else { + appClient.tracer = &tracing.NoopTracer{} + } + if f.configManager != nil { appClient.ConfigManager = f.configManager } else { @@ -300,6 +308,12 @@ func WithNotificationCenter(nc notification.Center) OptionFunc { } } +func WithTracer(tracer tracing.Tracer) OptionFunc { + return func(f *OptimizelyFactory) { + f.tracer = tracer + } +} + // StaticClient returns a client initialized with a static project config. func (f *OptimizelyFactory) StaticClient() (optlyClient *OptimizelyClient, err error) { diff --git a/pkg/tracing/opentelemetry.go b/pkg/tracing/opentelemetry.go new file mode 100644 index 00000000..37dd3d4d --- /dev/null +++ b/pkg/tracing/opentelemetry.go @@ -0,0 +1,60 @@ +package tracing + +import ( + "context" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +type Span interface { + End() + SetAttibutes(key string, value interface{}) +} + +type otelSpan struct { + span trace.Span +} + +func (s *otelSpan) SetAttibutes(key string, value interface{}) { + s.span.SetAttributes(attribute.KeyValue{ + Key: attribute.Key(key), + Value: attribute.StringValue(value.(string)), + }) +} + +func (s *otelSpan) End() { + s.span.End() +} + +type Tracer interface { + StartSpan(ctx context.Context, spanName string) (context.Context, Span) +} + +type otelTracer struct { + tracer trace.Tracer +} + +func NewOtelTracer(t trace.Tracer) Tracer { + return &otelTracer{ + tracer: t, + } +} + +func (t *otelTracer) StartSpan(pctx context.Context, spanName string) (context.Context, Span) { + ctx, span := t.tracer.Start(pctx, spanName) + return ctx, &otelSpan{ + span: span, + } +} + +type NoopTracer struct{} + +func (t *NoopTracer) StartSpan(ctx context.Context, spanName string) (context.Context, Span) { + return ctx, &NoopSpan{} +} + +type NoopSpan struct{} + +func (s *NoopSpan) SetAttibutes(key string, value interface{}) {} +func (s *NoopSpan) End() {} From e9e5e79e981d87037d4045323d3154740698802f Mon Sep 17 00:00:00 2001 From: Pulak Bhowmick Date: Fri, 1 Dec 2023 19:41:04 +0600 Subject: [PATCH 2/6] add tracing for track event --- pkg/client/client.go | 11 ++++---- pkg/client/client_test.go | 38 ++++++++++++++++----------- pkg/client/optimizely_user_context.go | 3 ++- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/pkg/client/client.go b/pkg/client/client.go index 65a0f58b..73f1b960 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -69,10 +69,6 @@ func (o *OptimizelyClient) CreateUserContext(userID string, attributes map[strin } func (o *OptimizelyClient) decide(userContext OptimizelyUserContext, key string, options *decide.Options) OptimizelyDecision { - // TODO: we need to change userContext to carry a context from the caller to use in StartSpan - _, span := o.tracer.StartSpan(context.TODO(), "decide") - defer span.End() - var err error defer func() { if r := recover(); r != nil { @@ -89,7 +85,6 @@ func (o *OptimizelyClient) decide(userContext OptimizelyUserContext, key string, o.logger.Debug(string(debug.Stack())) } }() - decisionContext := decision.FeatureDecisionContext{ ForcedDecisionService: userContext.forcedDecisionService, } @@ -845,7 +840,7 @@ func (o *OptimizelyClient) GetVariation(experimentKey string, userContext entiti // Track generates a conversion event with the given event key if it exists and queues it up to be sent to the Optimizely // log endpoint for results processing. -func (o *OptimizelyClient) Track(eventKey string, userContext entities.UserContext, eventTags map[string]interface{}) (err error) { +func (o *OptimizelyClient) Track(ctx context.Context, eventKey string, userContext entities.UserContext, eventTags map[string]interface{}) (err error) { defer func() { if r := recover(); r != nil { @@ -863,6 +858,10 @@ func (o *OptimizelyClient) Track(eventKey string, userContext entities.UserConte } }() + // TODO: we need to change userContext to carry a context from the caller to use in StartSpan + _, span := o.tracer.StartSpan(ctx, "track-sdk") + defer span.End() + projectConfig, e := o.getProjectConfig() if e != nil { o.logger.Error("Optimizely SDK tracking error", e) diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index adade6de..c324c714 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -35,6 +35,7 @@ import ( "github.com/optimizely/go-sdk/pkg/odp" "github.com/optimizely/go-sdk/pkg/odp/segment" pkgOdpUtils "github.com/optimizely/go-sdk/pkg/odp/utils" + "github.com/optimizely/go-sdk/pkg/tracing" "github.com/optimizely/go-sdk/pkg/utils" "github.com/stretchr/testify/assert" @@ -322,9 +323,10 @@ func TestTrack(t *testing.T) { DecisionService: mockDecisionService, EventProcessor: mockProcessor, logger: logging.GetLogger("", ""), + tracer: &tracing.NoopTracer{}, } - err := client.Track("sample_conversion", entities.UserContext{ID: "1212121", Attributes: map[string]interface{}{}}, map[string]interface{}{}) + err := client.Track(context.Background(), "sample_conversion", entities.UserContext{ID: "1212121", Attributes: map[string]interface{}{}}, map[string]interface{}{}) assert.NoError(t, err) assert.True(t, len(mockProcessor.Events) == 1) @@ -342,9 +344,10 @@ func TestTrackFailEventNotFound(t *testing.T) { DecisionService: mockDecisionService, EventProcessor: mockProcessor, logger: logging.GetLogger("", ""), + tracer: &tracing.NoopTracer{}, } - err := client.Track("bob", entities.UserContext{ID: "1212121", Attributes: map[string]interface{}{}}, map[string]interface{}{}) + err := client.Track(context.Background(), "bob", entities.UserContext{ID: "1212121", Attributes: map[string]interface{}{}}, map[string]interface{}{}) assert.NoError(t, err) assert.True(t, len(mockProcessor.Events) == 0) @@ -360,9 +363,10 @@ func TestTrackPanics(t *testing.T) { DecisionService: mockDecisionService, EventProcessor: mockProcessor, logger: logging.GetLogger("", ""), + tracer: &tracing.NoopTracer{}, } - err := client.Track("bob", entities.UserContext{ID: "1212121", Attributes: map[string]interface{}{}}, map[string]interface{}{}) + err := client.Track(context.Background(), "bob", entities.UserContext{ID: "1212121", Attributes: map[string]interface{}{}}, map[string]interface{}{}) assert.Error(t, err) assert.True(t, len(mockProcessor.Events) == 0) @@ -2730,6 +2734,7 @@ func (s *ClientTestSuiteTrackEvent) SetupTest() { EventProcessor: s.mockProcessor, notificationCenter: notification.NewNotificationCenter(), logger: logging.GetLogger("", ""), + tracer: &tracing.NoopTracer{}, } } @@ -2750,7 +2755,7 @@ func (s *ClientTestSuiteTrackEvent) TestTrackWithNotification() { s.Equal(1, id) s.NoError(err) - err = s.client.Track("sample_conversion", expectedUserContext, map[string]interface{}{}) + err = s.client.Track(context.Background(), "sample_conversion", expectedUserContext, map[string]interface{}{}) s.NoError(err) s.True(isTrackCalled) s.Equal(1, len(s.mockProcessor.Events)) @@ -2776,7 +2781,7 @@ func (s *ClientTestSuiteTrackEvent) TestTrackWithNotificationAndEventTag() { } s.client.OnTrack(onTrack) - err := s.client.Track("sample_conversion", expectedUserContext, expectedEvenTags) + err := s.client.Track(context.Background(), "sample_conversion", expectedUserContext, expectedEvenTags) s.NoError(err) s.True(isTrackCalled) @@ -2804,7 +2809,7 @@ func (s *ClientTestSuiteTrackEvent) TestTrackWithNotificationAndUserEvent() { } s.client.OnTrack(onTrack) - err := s.client.Track("sample_conversion", expectedUserContext, expectedEventTags) + err := s.client.Track(context.Background(), "sample_conversion", expectedUserContext, expectedEventTags) s.NoError(err) s.True(isTrackCalled) @@ -2822,7 +2827,7 @@ func (s *ClientTestSuiteTrackEvent) TestTrackNotificationNotCalledWhenEventProce } s.client.OnTrack(onTrack) - err := s.client.Track("sample_conversion", entities.UserContext{ID: "1212121", Attributes: map[string]interface{}{}}, map[string]interface{}{}) + err := s.client.Track(context.Background(), "sample_conversion", entities.UserContext{ID: "1212121", Attributes: map[string]interface{}{}}, map[string]interface{}{}) s.NoError(err) s.Equal(0, len(s.mockProcessor.Events)) s.False(isTrackCalled) @@ -2840,7 +2845,7 @@ func (s *ClientTestSuiteTrackEvent) TestTrackNotificationNotCalledWhenNoNotifica } s.client.notificationCenter = nil s.client.OnTrack(onTrack) - err := s.client.Track("sample_conversion", userContext, map[string]interface{}{}) + err := s.client.Track(context.Background(), "sample_conversion", userContext, map[string]interface{}{}) s.NoError(err) s.False(isTrackCalled) @@ -2854,7 +2859,7 @@ func (s *ClientTestSuiteTrackEvent) TestTrackNotificationNotCalledWhenInvalidEve } s.client.OnTrack(onTrack) - err := s.client.Track("bob", entities.UserContext{ID: "1212121", Attributes: map[string]interface{}{}}, map[string]interface{}{}) + err := s.client.Track(context.Background(), "bob", entities.UserContext{ID: "1212121", Attributes: map[string]interface{}{}}, map[string]interface{}{}) s.NoError(err) s.Equal(0, len(s.mockProcessor.Events)) @@ -2883,7 +2888,7 @@ func (s *ClientTestSuiteTrackEvent) TestTrackNotificationNotCalledWhenSendThrows mockNotificationCenter.On("AddHandler", notification.Track, mock.AnythingOfType("func(interface {})")).Return(1, nil) s.client.notificationCenter = mockNotificationCenter s.client.OnTrack(onTrack) - err = s.client.Track("sample_conversion", expectedUserContext, map[string]interface{}{}) + err = s.client.Track(context.Background(), "sample_conversion", expectedUserContext, map[string]interface{}{}) s.NoError(err) s.Equal(1, len(s.mockProcessor.Events)) @@ -2909,6 +2914,7 @@ func (s *ClientTestSuiteTrackNotification) SetupTest() { EventProcessor: s.mockProcessor, notificationCenter: notification.NewNotificationCenter(), logger: logging.GetLogger("", ""), + tracer: &tracing.NoopTracer{}, } } @@ -2931,7 +2937,7 @@ func (s *ClientTestSuiteTrackNotification) TestMultipleOnTrack() { // Add 5 on track callbacks addOnTrack(5) - err := s.client.Track("sample_conversion", userContext, map[string]interface{}{}) + err := s.client.Track(context.Background(), "sample_conversion", userContext, map[string]interface{}{}) s.NoError(err) s.Equal(5, numberOfCalls) } @@ -2954,7 +2960,7 @@ func (s *ClientTestSuiteTrackNotification) TestMultipleRemoveOnTrack() { s.NoError(err) } - err := s.client.Track("sample_conversion", userContext, map[string]interface{}{}) + err := s.client.Track(context.Background(), "sample_conversion", userContext, map[string]interface{}{}) s.NoError(err) s.Equal(5, numberOfCalls) @@ -2965,7 +2971,7 @@ func (s *ClientTestSuiteTrackNotification) TestMultipleRemoveOnTrack() { s.NoError(err) } - err = s.client.Track("sample_conversion", userContext, map[string]interface{}{}) + err = s.client.Track(context.Background(), "sample_conversion", userContext, map[string]interface{}{}) s.NoError(err) s.Equal(0, numberOfCalls) } @@ -2989,7 +2995,7 @@ func (s *ClientTestSuiteTrackNotification) TestOnTrackAfterRemoveOnTrack() { // Add 5 on track callbacks addOnTrack(5) - err := s.client.Track("sample_conversion", userContext, map[string]interface{}{}) + err := s.client.Track(context.Background(), "sample_conversion", userContext, map[string]interface{}{}) s.NoError(err) s.Equal(5, numberOfCalls) @@ -2999,13 +3005,13 @@ func (s *ClientTestSuiteTrackNotification) TestOnTrackAfterRemoveOnTrack() { err = s.client.RemoveOnTrack(callbackIds[i]) s.NoError(err) } - err = s.client.Track("sample_conversion", userContext, map[string]interface{}{}) + err = s.client.Track(context.Background(), "sample_conversion", userContext, map[string]interface{}{}) s.NoError(err) s.Equal(0, numberOfCalls) // Add 2 on track callbacks addOnTrack(2) - err = s.client.Track("sample_conversion", userContext, map[string]interface{}{}) + err = s.client.Track(context.Background(), "sample_conversion", userContext, map[string]interface{}{}) s.NoError(err) s.Equal(2, numberOfCalls) } diff --git a/pkg/client/optimizely_user_context.go b/pkg/client/optimizely_user_context.go index 297ef638..8a711537 100644 --- a/pkg/client/optimizely_user_context.go +++ b/pkg/client/optimizely_user_context.go @@ -18,6 +18,7 @@ package client import ( + "context" "errors" "sync" @@ -154,7 +155,7 @@ func (o *OptimizelyUserContext) TrackEvent(eventKey string, eventTags map[string ID: o.GetUserID(), Attributes: o.GetUserAttributes(), } - return o.optimizely.Track(eventKey, userContext, eventTags) + return o.optimizely.Track(context.Background(), eventKey, userContext, eventTags) } // SetForcedDecision sets the forced decision (variation key) for a given decision context (flag key and optional rule key). From 3fc8057e324193f58346250d577ddaca2064ca77 Mon Sep 17 00:00:00 2001 From: Pulak Bhowmick Date: Fri, 1 Dec 2023 20:17:20 +0600 Subject: [PATCH 3/6] update version --- go.mod | 4 ++-- go.sum | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index d3a22b2d..a69c7897 100644 --- a/go.mod +++ b/go.mod @@ -10,8 +10,8 @@ require ( github.com/pkg/profile v1.7.0 github.com/stretchr/testify v1.8.4 github.com/twmb/murmur3 v1.1.6 - go.opentelemetry.io/otel v1.21.0 - go.opentelemetry.io/otel/trace v1.21.0 + go.opentelemetry.io/otel v1.19.0 + go.opentelemetry.io/otel/trace v1.19.0 golang.org/x/sync v0.1.0 ) diff --git a/go.sum b/go.sum index 0b84da8a..91aa9b3b 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ 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/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= @@ -43,10 +43,10 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 8cf34c2a8673b7355e96597c9e5793f7778e2bd5 Mon Sep 17 00:00:00 2001 From: Pulak Bhowmick Date: Fri, 1 Dec 2023 23:39:25 +0600 Subject: [PATCH 4/6] update otel tracer --- go.mod | 3 +++ go.sum | 7 +++++++ pkg/client/client.go | 2 +- pkg/tracing/opentelemetry.go | 9 +++++---- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index a69c7897..131a40d5 100644 --- a/go.mod +++ b/go.mod @@ -18,11 +18,14 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/felixge/fgprof v0.9.3 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.5.0 // indirect + go.opentelemetry.io/otel/metric v1.19.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 91aa9b3b..80cf8ba9 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,11 @@ 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/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -45,6 +50,8 @@ github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= diff --git a/pkg/client/client.go b/pkg/client/client.go index 73f1b960..6a6bbb18 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -859,7 +859,7 @@ func (o *OptimizelyClient) Track(ctx context.Context, eventKey string, userConte }() // TODO: we need to change userContext to carry a context from the caller to use in StartSpan - _, span := o.tracer.StartSpan(ctx, "track-sdk") + _, span := o.tracer.StartSpan(ctx, "trackHandler", "trackSDK") defer span.End() projectConfig, e := o.getProjectConfig() diff --git a/pkg/tracing/opentelemetry.go b/pkg/tracing/opentelemetry.go index 37dd3d4d..10fcaaa9 100644 --- a/pkg/tracing/opentelemetry.go +++ b/pkg/tracing/opentelemetry.go @@ -3,6 +3,7 @@ package tracing import ( "context" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) @@ -28,7 +29,7 @@ func (s *otelSpan) End() { } type Tracer interface { - StartSpan(ctx context.Context, spanName string) (context.Context, Span) + StartSpan(ctx context.Context, tracerName, spanName string) (context.Context, Span) } type otelTracer struct { @@ -41,8 +42,8 @@ func NewOtelTracer(t trace.Tracer) Tracer { } } -func (t *otelTracer) StartSpan(pctx context.Context, spanName string) (context.Context, Span) { - ctx, span := t.tracer.Start(pctx, spanName) +func (t *otelTracer) StartSpan(pctx context.Context, tracerName, spanName string) (context.Context, Span) { + ctx, span := otel.Tracer(tracerName).Start(pctx, spanName) return ctx, &otelSpan{ span: span, } @@ -50,7 +51,7 @@ func (t *otelTracer) StartSpan(pctx context.Context, spanName string) (context.C type NoopTracer struct{} -func (t *NoopTracer) StartSpan(ctx context.Context, spanName string) (context.Context, Span) { +func (t *NoopTracer) StartSpan(ctx context.Context, tracerName string, spanName string) (context.Context, Span) { return ctx, &NoopSpan{} } From 855ceaa12c87c724e80cc4068d7196e4c167215f Mon Sep 17 00:00:00 2001 From: Pulak Bhowmick Date: Mon, 4 Dec 2023 17:53:44 +0600 Subject: [PATCH 5/6] update sdk implementation --- pkg/client/client.go | 3 ++- pkg/tracing/opentelemetry.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/client/client.go b/pkg/client/client.go index 6a6bbb18..eaa3ae9e 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -858,10 +858,11 @@ func (o *OptimizelyClient) Track(ctx context.Context, eventKey string, userConte } }() - // TODO: we need to change userContext to carry a context from the caller to use in StartSpan _, span := o.tracer.StartSpan(ctx, "trackHandler", "trackSDK") defer span.End() + span.SetAttibutes("testTrackKey", "testTrackValue") + projectConfig, e := o.getProjectConfig() if e != nil { o.logger.Error("Optimizely SDK tracking error", e) diff --git a/pkg/tracing/opentelemetry.go b/pkg/tracing/opentelemetry.go index 10fcaaa9..1eb72229 100644 --- a/pkg/tracing/opentelemetry.go +++ b/pkg/tracing/opentelemetry.go @@ -33,12 +33,12 @@ type Tracer interface { } type otelTracer struct { - tracer trace.Tracer + enabled bool } func NewOtelTracer(t trace.Tracer) Tracer { return &otelTracer{ - tracer: t, + enabled: true, } } From f230d0b8d5da7dce13e865fec43979de3b4764d0 Mon Sep 17 00:00:00 2001 From: Pulak Bhowmick Date: Wed, 6 Dec 2023 21:58:45 +0600 Subject: [PATCH 6/6] add comments --- pkg/tracing/opentelemetry.go | 44 ++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/pkg/tracing/opentelemetry.go b/pkg/tracing/opentelemetry.go index 1eb72229..66da3d6a 100644 --- a/pkg/tracing/opentelemetry.go +++ b/pkg/tracing/opentelemetry.go @@ -8,30 +8,20 @@ import ( "go.opentelemetry.io/otel/trace" ) +// Tracer provides the necessary method to collect telemetry trace data. +// Tracer should not depend on any specific tool. To make it possible it returns a Span interface. +type Tracer interface { + // StartSpan starts a trace span. Span can be a parent or child span based on the passed context. + StartSpan(ctx context.Context, tracerName, spanName string) (context.Context, Span) +} + +// Span interface implements the trace span returned by Tracer. type Span interface { End() SetAttibutes(key string, value interface{}) } -type otelSpan struct { - span trace.Span -} - -func (s *otelSpan) SetAttibutes(key string, value interface{}) { - s.span.SetAttributes(attribute.KeyValue{ - Key: attribute.Key(key), - Value: attribute.StringValue(value.(string)), - }) -} - -func (s *otelSpan) End() { - s.span.End() -} - -type Tracer interface { - StartSpan(ctx context.Context, tracerName, spanName string) (context.Context, Span) -} - +// otelTracer is an OpenTelemetry implementation of Tracer type otelTracer struct { enabled bool } @@ -49,6 +39,22 @@ func (t *otelTracer) StartSpan(pctx context.Context, tracerName, spanName string } } +// otelSpan is an OpenTelemetry Span implementation of Span +type otelSpan struct { + span trace.Span +} + +func (s *otelSpan) SetAttibutes(key string, value interface{}) { + s.span.SetAttributes(attribute.KeyValue{ + Key: attribute.Key(key), + Value: attribute.StringValue(value.(string)), + }) +} + +func (s *otelSpan) End() { + s.span.End() +} + type NoopTracer struct{} func (t *NoopTracer) StartSpan(ctx context.Context, tracerName string, spanName string) (context.Context, Span) {