diff --git a/contrib/Shopify/sarama/option.go b/contrib/Shopify/sarama/option.go index 2e27cee9ef..2b6e12cbd2 100644 --- a/contrib/Shopify/sarama/option.go +++ b/contrib/Shopify/sarama/option.go @@ -7,15 +7,22 @@ package sarama import ( "math" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" ) type config struct { - serviceName string - analyticsRate float64 + consumerServiceName string + producerServiceName string + analyticsRate float64 } func defaults(cfg *config) { - cfg.serviceName = "kafka" + cfg.producerServiceName = "kafka" + cfg.consumerServiceName = "kafka" + if svc := globalconfig.ServiceName(); svc != "" { + cfg.consumerServiceName = svc + } // cfg.analyticsRate = globalconfig.AnalyticsRate() cfg.analyticsRate = math.NaN() } @@ -26,7 +33,8 @@ type Option func(cfg *config) // WithServiceName sets the given service name for the intercepted client. func WithServiceName(name string) Option { return func(cfg *config) { - cfg.serviceName = name + cfg.consumerServiceName = name + cfg.producerServiceName = name } } diff --git a/contrib/Shopify/sarama/sarama.go b/contrib/Shopify/sarama/sarama.go index 933f5532b1..aee8d785d7 100644 --- a/contrib/Shopify/sarama/sarama.go +++ b/contrib/Shopify/sarama/sarama.go @@ -45,7 +45,7 @@ func WrapPartitionConsumer(pc sarama.PartitionConsumer, opts ...Option) sarama.P for msg := range msgs { // create the next span from the message opts := []tracer.StartSpanOption{ - tracer.ServiceName(cfg.serviceName), + tracer.ServiceName(cfg.consumerServiceName), tracer.ResourceName("Consume Topic " + msg.Topic), tracer.SpanType(ext.SpanTypeMessageConsumer), tracer.Tag("partition", msg.Partition), @@ -246,7 +246,7 @@ func WrapAsyncProducer(saramaConfig *sarama.Config, p sarama.AsyncProducer, opts func startProducerSpan(cfg *config, version sarama.KafkaVersion, msg *sarama.ProducerMessage) ddtrace.Span { carrier := NewProducerMessageCarrier(msg) opts := []tracer.StartSpanOption{ - tracer.ServiceName(cfg.serviceName), + tracer.ServiceName(cfg.producerServiceName), tracer.ResourceName("Produce Topic " + msg.Topic), tracer.SpanType(ext.SpanTypeMessageProducer), } diff --git a/contrib/confluentinc/confluent-kafka-go/kafka/kafka.go b/contrib/confluentinc/confluent-kafka-go/kafka/kafka.go index 2950d8a9d9..355a6fc2f6 100644 --- a/contrib/confluentinc/confluent-kafka-go/kafka/kafka.go +++ b/contrib/confluentinc/confluent-kafka-go/kafka/kafka.go @@ -88,7 +88,7 @@ func (c *Consumer) traceEventsChannel(in chan kafka.Event) chan kafka.Event { func (c *Consumer) startSpan(msg *kafka.Message) ddtrace.Span { opts := []tracer.StartSpanOption{ - tracer.ServiceName(c.cfg.serviceName), + tracer.ServiceName(c.cfg.consumerServiceName), tracer.ResourceName("Consume Topic " + *msg.TopicPartition.Topic), tracer.SpanType(ext.SpanTypeMessageConsumer), tracer.Tag("partition", msg.TopicPartition.Partition), @@ -179,7 +179,7 @@ func (p *Producer) traceProduceChannel(out chan *kafka.Message) chan *kafka.Mess func (p *Producer) startSpan(msg *kafka.Message) ddtrace.Span { opts := []tracer.StartSpanOption{ - tracer.ServiceName(p.cfg.serviceName), + tracer.ServiceName(p.cfg.producerServiceName), tracer.ResourceName("Produce Topic " + *msg.TopicPartition.Topic), tracer.SpanType(ext.SpanTypeMessageProducer), tracer.Tag("partition", msg.TopicPartition.Partition), diff --git a/contrib/confluentinc/confluent-kafka-go/kafka/option.go b/contrib/confluentinc/confluent-kafka-go/kafka/option.go index 86f7bfef4a..0e5e163c20 100644 --- a/contrib/confluentinc/confluent-kafka-go/kafka/option.go +++ b/contrib/confluentinc/confluent-kafka-go/kafka/option.go @@ -8,12 +8,15 @@ package kafka import ( "context" "math" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" ) type config struct { - ctx context.Context - serviceName string - analyticsRate float64 + ctx context.Context + consumerServiceName string + producerServiceName string + analyticsRate float64 } // An Option customizes the config. @@ -21,11 +24,15 @@ type Option func(cfg *config) func newConfig(opts ...Option) *config { cfg := &config{ - serviceName: "kafka", - ctx: context.Background(), + ctx: context.Background(), + consumerServiceName: "kafka", + producerServiceName: "kafka", // analyticsRate: globalconfig.AnalyticsRate(), analyticsRate: math.NaN(), } + if svc := globalconfig.ServiceName(); svc != "" { + cfg.consumerServiceName = svc + } for _, opt := range opts { opt(cfg) } @@ -42,7 +49,8 @@ func WithContext(ctx context.Context) Option { // WithServiceName sets the config service name to serviceName. func WithServiceName(serviceName string) Option { return func(cfg *config) { - cfg.serviceName = serviceName + cfg.consumerServiceName = serviceName + cfg.producerServiceName = serviceName } } diff --git a/contrib/go-chi/chi/option.go b/contrib/go-chi/chi/option.go index e4bd9d67fd..d3f5a49c33 100644 --- a/contrib/go-chi/chi/option.go +++ b/contrib/go-chi/chi/option.go @@ -23,6 +23,9 @@ type Option func(*config) func defaults(cfg *config) { cfg.serviceName = "chi.router" + if svc := globalconfig.ServiceName(); svc != "" { + cfg.serviceName = svc + } cfg.analyticsRate = globalconfig.AnalyticsRate() } diff --git a/contrib/google.golang.org/grpc.v12/grpc.go b/contrib/google.golang.org/grpc.v12/grpc.go index 9850e7eb2c..f2ba0771e0 100644 --- a/contrib/google.golang.org/grpc.v12/grpc.go +++ b/contrib/google.golang.org/grpc.v12/grpc.go @@ -16,6 +16,7 @@ import ( "gopkg.in/DataDog/dd-trace-go.v1/ddtrace" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" context "golang.org/x/net/context" "google.golang.org/grpc" @@ -32,6 +33,9 @@ func UnaryServerInterceptor(opts ...InterceptorOption) grpc.UnaryServerIntercept } if cfg.serviceName == "" { cfg.serviceName = "grpc.server" + if svc := globalconfig.ServiceName(); svc != "" { + cfg.serviceName = svc + } } return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { span, ctx := startSpanFromContext(ctx, info.FullMethod, cfg.serviceName, cfg.analyticsRate) diff --git a/contrib/google.golang.org/grpc/option.go b/contrib/google.golang.org/grpc/option.go index 1e9a286bd1..c6c7d021e2 100644 --- a/contrib/google.golang.org/grpc/option.go +++ b/contrib/google.golang.org/grpc/option.go @@ -8,6 +8,8 @@ package grpc import ( "math" + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" + "google.golang.org/grpc/codes" ) @@ -27,7 +29,10 @@ type config struct { func (cfg *config) serverServiceName() string { if cfg.serviceName == "" { - return "grpc.server" + cfg.serviceName = "grpc.server" + if svc := globalconfig.ServiceName(); svc != "" { + cfg.serviceName = svc + } } return cfg.serviceName } diff --git a/contrib/gorilla/mux/option.go b/contrib/gorilla/mux/option.go index 9be556b9d8..b7f34c55be 100644 --- a/contrib/gorilla/mux/option.go +++ b/contrib/gorilla/mux/option.go @@ -28,6 +28,9 @@ type RouterOption func(*routerConfig) func defaults(cfg *routerConfig) { cfg.analyticsRate = globalconfig.AnalyticsRate() cfg.serviceName = "mux.router" + if svc := globalconfig.ServiceName(); svc != "" { + cfg.serviceName = svc + } cfg.resourceNamer = defaultResourceNamer } diff --git a/contrib/graph-gophers/graphql-go/option.go b/contrib/graph-gophers/graphql-go/option.go index a3b2e8e767..b1e4eebb25 100644 --- a/contrib/graph-gophers/graphql-go/option.go +++ b/contrib/graph-gophers/graphql-go/option.go @@ -7,6 +7,8 @@ package graphql import ( "math" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" ) type config struct { @@ -19,6 +21,9 @@ type Option func(*config) func defaults(cfg *config) { cfg.serviceName = "graphql.server" + if svc := globalconfig.ServiceName(); svc != "" { + cfg.serviceName = svc + } // cfg.analyticsRate = globalconfig.AnalyticsRate() cfg.analyticsRate = math.NaN() } diff --git a/contrib/julienschmidt/httprouter/option.go b/contrib/julienschmidt/httprouter/option.go index c2e6989125..122a45bf7a 100644 --- a/contrib/julienschmidt/httprouter/option.go +++ b/contrib/julienschmidt/httprouter/option.go @@ -24,6 +24,9 @@ type RouterOption func(*routerConfig) func defaults(cfg *routerConfig) { cfg.analyticsRate = globalconfig.AnalyticsRate() cfg.serviceName = "http.router" + if svc := globalconfig.ServiceName(); svc != "" { + cfg.serviceName = svc + } } // WithServiceName sets the given service name for the returned router. diff --git a/contrib/labstack/echo/option.go b/contrib/labstack/echo/option.go index 729b8b2cb0..c9658e647d 100644 --- a/contrib/labstack/echo/option.go +++ b/contrib/labstack/echo/option.go @@ -7,6 +7,8 @@ package echo import ( "math" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" ) type config struct { @@ -19,6 +21,9 @@ type Option func(*config) func defaults(cfg *config) { cfg.serviceName = "echo" + if svc := globalconfig.ServiceName(); svc != "" { + cfg.serviceName = svc + } cfg.analyticsRate = math.NaN() } diff --git a/contrib/net/http/option.go b/contrib/net/http/option.go index 0cce41203e..828a76aa17 100644 --- a/contrib/net/http/option.go +++ b/contrib/net/http/option.go @@ -31,6 +31,9 @@ type Option func(*config) func defaults(cfg *config) { cfg.analyticsRate = globalconfig.AnalyticsRate() cfg.serviceName = "http.router" + if svc := globalconfig.ServiceName(); svc != "" { + cfg.serviceName = svc + } cfg.spanOpts = []ddtrace.StartSpanOption{tracer.Measured()} if !math.IsNaN(cfg.analyticsRate) { cfg.spanOpts = append(cfg.spanOpts, tracer.Tag(ext.EventSampleRate, cfg.analyticsRate)) diff --git a/ddtrace/tracer/option.go b/ddtrace/tracer/option.go index ec651b3473..9b508a58c7 100644 --- a/ddtrace/tracer/option.go +++ b/ddtrace/tracer/option.go @@ -110,6 +110,7 @@ func defaults(c *config) { } if v := os.Getenv("DD_SERVICE"); v != "" { c.serviceName = v + globalconfig.SetServiceName(v) } else { c.serviceName = filepath.Base(os.Args[0]) } @@ -186,16 +187,26 @@ func WithPropagator(p Propagator) StartOption { } } -// WithServiceName sets the default service name to be used with the tracer. It is -// deprecated in favour of WithService and will be removed in the next major version. +// WithServiceName is deprecated. Please use WithService. +// If you are using an older version and you are upgrading from WithServiceName +// to WithService, please note that WithService will determine the service name of +// server and framework integrations. func WithServiceName(name string) StartOption { - return WithService(name) + return func(c *config) { + c.serviceName = name + if globalconfig.ServiceName() != "" { + log.Warn("ddtrace/tracer: deprecated config WithServiceName should not be used " + + "with `WithService` or `DD_SERVICE`; integration service name will not be set.") + } + globalconfig.SetServiceName("") + } } -// WithService sets the default service name to be used with the tracer. +// WithService sets the default service name for the program. func WithService(name string) StartOption { return func(c *config) { c.serviceName = name + globalconfig.SetServiceName(c.serviceName) } } diff --git a/ddtrace/tracer/option_test.go b/ddtrace/tracer/option_test.go index 7574f3f29f..a1f1da8324 100644 --- a/ddtrace/tracer/option_test.go +++ b/ddtrace/tracer/option_test.go @@ -114,7 +114,6 @@ func TestTracerOptionsDefaults(t *testing.T) { assert := assert.New(t) tracer := newTracer( WithSampler(NewRateSampler(0.5)), - WithServiceName("api-intake"), WithAgentAddr("ddagent.consul.local:58126"), WithGlobalTag("k", "v"), WithDebugMode(true), @@ -122,7 +121,6 @@ func TestTracerOptionsDefaults(t *testing.T) { ) c := tracer.config assert.Equal(float64(0.5), c.sampler.(RateSampler).Rate()) - assert.Equal("api-intake", c.serviceName) assert.Equal("ddagent.consul.local:58126", c.agentAddr) assert.NotNil(c.globalTags) assert.Equal("v", c.globalTags["k"]) @@ -130,16 +128,6 @@ func TestTracerOptionsDefaults(t *testing.T) { assert.True(c.debug) }) - t.Run("env-service", func(t *testing.T) { - os.Setenv("DD_SERVICE", "TEST_SERVICE") - defer os.Unsetenv("DD_SERVICE") - - assert := assert.New(t) - var c config - defaults(&c) - assert.Equal("TEST_SERVICE", c.serviceName) - }) - t.Run("env-tags", func(t *testing.T) { os.Setenv("DD_TAGS", "env:test, aKey:aVal,bKey:bVal, cKey:") defer os.Unsetenv("DD_TAGS") @@ -158,3 +146,47 @@ func TestTracerOptionsDefaults(t *testing.T) { assert.Equal(nil, dVal) }) } + +func TestServiceName(t *testing.T) { + t.Run("WithServiceName", func(t *testing.T) { + assert := assert.New(t) + tracer := newTracer( + WithServiceName("api-intake"), + ) + + assert.Equal("api-intake", tracer.config.serviceName) + assert.Equal("", globalconfig.ServiceName()) + }) + + t.Run("WithService", func(t *testing.T) { + assert := assert.New(t) + tracer := newTracer( + WithService("api-intake"), + ) + assert.Equal("api-intake", tracer.config.serviceName) + assert.Equal("api-intake", globalconfig.ServiceName()) + }) + + t.Run("env", func(t *testing.T) { + os.Setenv("DD_SERVICE", "api-intake") + defer os.Unsetenv("DD_SERVICE") + assert := assert.New(t) + tracer := newTracer() + + assert.Equal("api-intake", tracer.config.serviceName) + assert.Equal("api-intake", globalconfig.ServiceName()) + }) + + t.Run("combo", func(t *testing.T) { + os.Setenv("DD_SERVICE", "api-intake") + defer os.Unsetenv("DD_SERVICE") + assert := assert.New(t) + + tracer := newTracer( + WithServiceName("api-intake"), + ) + + assert.Equal("api-intake", tracer.config.serviceName) + assert.Equal("", globalconfig.ServiceName()) + }) +} diff --git a/internal/globalconfig/globalconfig.go b/internal/globalconfig/globalconfig.go index a4557b98bc..d1ae4f961f 100644 --- a/internal/globalconfig/globalconfig.go +++ b/internal/globalconfig/globalconfig.go @@ -19,6 +19,7 @@ var cfg = &config{ type config struct { mu sync.RWMutex analyticsRate float64 + serviceName string } // AnalyticsRate returns the sampling rate at which events should be marked. It uses @@ -36,3 +37,17 @@ func SetAnalyticsRate(rate float64) { cfg.analyticsRate = rate cfg.mu.Unlock() } + +// ServiceName returns the default service name used by non-client integrations such as servers and frameworks. +func ServiceName() string { + cfg.mu.RLock() + defer cfg.mu.RUnlock() + return cfg.serviceName +} + +// SetServiceName sets the global service name set for this application. +func SetServiceName(name string) { + cfg.mu.RLock() + defer cfg.mu.RUnlock() + cfg.serviceName = name +}