Skip to content
3 changes: 2 additions & 1 deletion contrib/database/sql/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/DataDog/dd-trace-go/v2/appsec/events"
"github.com/DataDog/dd-trace-go/v2/ddtrace/ext"
"github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
"github.com/DataDog/dd-trace-go/v2/instrumentation"
"github.com/DataDog/dd-trace-go/v2/instrumentation/appsec/emitter/sqlsec"
"github.com/DataDog/dd-trace-go/v2/instrumentation/options"
)
Expand Down Expand Up @@ -329,7 +330,7 @@ func (tp *traceParams) tryTrace(ctx context.Context, qtype QueryType, query stri
dbSystem, _ := normalizeDBSystem(tp.driverName)
opts := options.Expand(spanOpts, 0, 6+len(tp.cfg.tags)+1)
opts = append(opts,
tracer.ServiceName(tp.cfg.serviceName),
instrumentation.ServiceNameWithSource(tp.cfg.serviceName, tp.cfg.serviceSource),
tracer.SpanType(ext.SpanTypeSQL),
tracer.StartTime(startTime),
tracer.Tag(ext.Component, componentName),
Expand Down
17 changes: 14 additions & 3 deletions contrib/database/sql/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ import (
"github.com/DataDog/dd-trace-go/v2/instrumentation/env"
)

// serviceSourceSQLDriver is the service source value used when the service
// name is derived from the driver name (e.g. database/sql Register driverName).
const serviceSourceSQLDriver = "opt.sql_driver"

type config struct {
serviceName string
serviceSource string
spanName string
analyticsRate float64
dsn string
Expand Down Expand Up @@ -144,7 +149,7 @@ func defaults(cfg *config, driverName string, rc *registerConfig) {
mode = env.Get("DD_TRACE_SQL_COMMENT_INJECTION_MODE")
}
cfg.dbmPropagationMode = tracer.DBMPropagationMode(mode)
cfg.serviceName = defaultServiceName(driverName, rc)
cfg.serviceName, cfg.serviceSource = defaultServiceNameAndSource(driverName, rc)
cfg.spanName = getSpanName(driverName)
if rc != nil {
// use registered config as the default value for some options
Expand All @@ -167,16 +172,21 @@ func defaults(cfg *config, driverName string, rc *registerConfig) {
}
}

func defaultServiceName(driverName string, rc *registerConfig) string {
func defaultServiceNameAndSource(driverName string, rc *registerConfig) (string, string) {
registerService := ""
serviceSource := serviceSourceSQLDriver
if rc != nil {
// if service name was set during Register, we use that value as default.
registerService = rc.serviceName
if rc.serviceSource != "" {
serviceSource = rc.serviceSource
}
}
return instr.ServiceName(instrumentation.ComponentDefault, instrumentation.OperationContext{
serviceName := instr.ServiceName(instrumentation.ComponentDefault, instrumentation.OperationContext{
"driverName": driverName,
"registerService": registerService,
})
return serviceName, serviceSource
}

func getSpanName(driverName string) string {
Expand All @@ -195,6 +205,7 @@ func getSpanName(driverName string) string {
func WithService(name string) OptionFn {
return func(cfg *config) {
cfg.serviceName = name
cfg.serviceSource = instrumentation.ServiceSourceWithServiceOption
}
}

Expand Down
54 changes: 54 additions & 0 deletions contrib/database/sql/option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import (
"github.com/DataDog/datadog-go/v5/statsd"
"github.com/go-sql-driver/mysql"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/DataDog/dd-trace-go/v2/ddtrace/ext"
"github.com/DataDog/dd-trace-go/v2/ddtrace/mocktracer"
"github.com/DataDog/dd-trace-go/v2/instrumentation/testutils"
)
Expand Down Expand Up @@ -147,3 +149,55 @@ func TestRegisteredTags(t *testing.T) {
assert.Nil(t, cfg.tags)
})
}

func TestServiceSourceDriverName(t *testing.T) {
t.Run("non-empty driver name sets sql_driver source", func(t *testing.T) {
mt := mocktracer.Start()
defer mt.Stop()
Register("postgres", &mysql.MySQLDriver{})
defer unregister("postgres")

db, err := Open("postgres", "test:test@tcp(127.0.0.1:3306)/test")
if err != nil {
log.Fatal(err)
}
defer db.Close()
mt.Reset()

rows, err := db.QueryContext(context.Background(), "SELECT 1")
assert.NoError(t, err)
rows.Close()

spans := mt.FinishedSpans()
require.True(t, len(spans) > 0)
for _, sp := range spans {
assert.Equal(t, "postgres.db", sp.Tag(ext.ServiceName))
assert.Equal(t, serviceSourceSQLDriver, sp.Tag(ext.KeyServiceSource))
}
})

t.Run("empty driver name still sets sql_driver source", func(t *testing.T) {
mt := mocktracer.Start()
defer mt.Stop()
Register("", &mysql.MySQLDriver{})
defer unregister("")

db, err := Open("", "test:test@tcp(127.0.0.1:3306)/test")
if err != nil {
log.Fatal(err)
}
defer db.Close()
mt.Reset()

rows, err := db.QueryContext(context.Background(), "SELECT 1")
assert.NoError(t, err)
rows.Close()

spans := mt.FinishedSpans()
require.True(t, len(spans) > 0)
for _, sp := range spans {
assert.Equal(t, ".db", sp.Tag(ext.ServiceName))
assert.Equal(t, serviceSourceSQLDriver, sp.Tag(ext.KeyServiceSource))
}
})
}
2 changes: 1 addition & 1 deletion contrib/gin-gonic/gin/gintrace.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func Middleware(service string, opts ...Option) gin.HandlerFunc {
}
instr.Logger().Debug("contrib/gin-gonic/gin: Configuring Middleware: Service: %s, %#v", cfg.serviceName, cfg)
spanOpts := []tracer.StartSpanOption{
tracer.ServiceName(cfg.serviceName),
instrumentation.ServiceNameWithSource(cfg.serviceName, cfg.serviceSource),
tracer.Tag(ext.Component, componentName),
tracer.Tag(ext.SpanKind, ext.SpanKindServer),
}
Expand Down
3 changes: 3 additions & 0 deletions contrib/gin-gonic/gin/gintrace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ func TestServiceName(t *testing.T) {
assert.Len(spans, 1)
span := spans[0]
assert.Equal("gin.router", span.Tag(ext.ServiceName))
assert.Equal(string(instrumentation.PackageGin), span.Tag(ext.KeyServiceSource))
})

t.Run("global", func(t *testing.T) {
Expand Down Expand Up @@ -686,6 +687,7 @@ func TestServiceName(t *testing.T) {
assert.Len(spans, 1)
span := spans[0]
assert.Equal("global-service", span.Tag(ext.ServiceName))
assert.Nil(span.Tag(ext.KeyServiceSource), "service source should not be set when service matches global service")
})

t.Run("custom", func(t *testing.T) {
Expand Down Expand Up @@ -716,6 +718,7 @@ func TestServiceName(t *testing.T) {
assert.Len(spans, 1)
span := spans[0]
assert.Equal("my-service", span.Tag(ext.ServiceName))
assert.Equal(serviceSourceGinMiddleware, span.Tag(ext.KeyServiceSource))
})
}

Expand Down
8 changes: 8 additions & 0 deletions contrib/gin-gonic/gin/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,32 @@ import (
// envServerErrorStatuses is the name of the env var used to specify error status codes on http server spans
const envServerErrorStatuses = "DD_TRACE_HTTP_SERVER_ERROR_STATUSES"

// serviceSourceGinMiddleware is the service source value used when the service
// name is set via gin's Middleware(serviceName) parameter.
const serviceSourceGinMiddleware = "opt.gin_middleware"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems inconsistent with serviceSourceSQLDriver.

This one is set when a user has explicitly passed in a serviceName parameter to Middleware, but serviceSourceSQLDriver is set in the default case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes the behaviors are actually different between the integrations

  • on gin if the string is empty, the default services become the tracer global service
  • on database/sql if the string is empty, the service still is built from it and results in .db

See the following tests

One of my planned follow-up is to deprecate these APIs that pushes/forces users to have service overrides that are then confusing in the product. Replacing them with the options WithService for those who want to keep the behaviour

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand this new property the source is the place where the name comes from.

For SQL opt.sql_driver is used when the name is set by the package. It makes sense here as well because the middleware is the origin of the name and when no name is given we fallback to another source (default)


type config struct {
analyticsRate float64
resourceNamer func(c *gin.Context) string
serviceName string
serviceSource string
ignoreRequest func(c *gin.Context) bool
isStatusError func(statusCode int) bool
useGinErrors bool
headerTags instrumentation.HeaderTags
}

func newConfig(serviceName string) *config {
serviceSource := serviceSourceGinMiddleware
if serviceName == "" {
serviceName = instr.ServiceName(instrumentation.ComponentServer, nil)
serviceSource = string(instrumentation.PackageGin)
}
cfg := &config{
analyticsRate: instr.AnalyticsRate(true),
resourceNamer: defaultResourceNamer,
serviceName: serviceName,
serviceSource: serviceSource,
ignoreRequest: func(_ *gin.Context) bool { return false },
useGinErrors: false,
headerTags: instr.HTTPHeadersAsTags(),
Expand Down
3 changes: 3 additions & 0 deletions contrib/google.golang.org/grpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) {
cs.method,
"grpc.message",
cs.cfg.serviceName.String(),
cs.cfg.serviceSource,
cs.cfg.startSpanOptions()...,
)
span.SetTag(ext.Component, componentName)
Expand All @@ -56,6 +57,7 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) {
cs.method,
"grpc.message",
cs.cfg.serviceName.String(),
cs.cfg.serviceSource,
cs.cfg.startSpanOptions()...,
)
span.SetTag(ext.Component, componentName)
Expand Down Expand Up @@ -173,6 +175,7 @@ func doClientRequest(
method,
cfg.spanName,
cfg.serviceName.String(),
cfg.serviceSource,
cfg.startSpanOptions(
tracer.Tag(ext.Component, componentName),
tracer.Tag(ext.SpanKind, ext.SpanKindClient))...,
Expand Down
4 changes: 2 additions & 2 deletions contrib/google.golang.org/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ func (cfg *config) startSpanOptions(opts ...tracer.StartSpanOption) []tracer.Sta
}

func startSpanFromContext(
ctx context.Context, method, operation string, serviceName string, opts ...tracer.StartSpanOption,
ctx context.Context, method, operation string, serviceName string, serviceSource string, opts ...tracer.StartSpanOption,
) (*tracer.Span, context.Context) {
methodElements := strings.SplitN(strings.TrimPrefix(method, "/"), "/", 2)
opts = append(opts,
tracer.ServiceName(serviceName),
instrumentation.ServiceNameWithSource(serviceName, serviceSource),
tracer.ResourceName(method),
tracer.Tag(tagMethodName, method),
spanTypeRPC,
Expand Down
4 changes: 4 additions & 0 deletions contrib/google.golang.org/grpc/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func (cs *cachedServiceName) String() string {

type config struct {
serviceName *cachedServiceName
serviceSource string
spanName string
nonErrorCodes map[codes.Code]bool
traceStreamCalls bool
Expand Down Expand Up @@ -86,6 +87,7 @@ func clientDefaults(cfg *config) {
cfg.serviceName = newCachedServiceName(func() string {
return instr.ServiceName(instrumentation.ComponentClient, nil)
})
cfg.serviceSource = string(instrumentation.PackageGRPC)
cfg.spanName = instr.OperationName(instrumentation.ComponentClient, nil)
defaults(cfg)
}
Expand All @@ -94,6 +96,7 @@ func serverDefaults(cfg *config) {
cfg.serviceName = newCachedServiceName(func() string {
return instr.ServiceName(instrumentation.ComponentServer, nil)
})
cfg.serviceSource = string(instrumentation.PackageGRPC)
cfg.spanName = instr.OperationName(instrumentation.ComponentServer, nil)
defaults(cfg)
}
Expand All @@ -104,6 +107,7 @@ func WithService(name string) OptionFn {
cfg.serviceName = newCachedServiceName(func() string {
return name
})
cfg.serviceSource = instrumentation.ServiceSourceWithServiceOption
}
}

Expand Down
4 changes: 4 additions & 0 deletions contrib/google.golang.org/grpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) {
ss.method,
"grpc.message",
ss.cfg.serviceName.String(),
ss.cfg.serviceSource,
ss.cfg.startSpanOptions(tracer.Measured())...,
)
span.SetTag(ext.Component, componentName)
Expand All @@ -65,6 +66,7 @@ func (ss *serverStream) SendMsg(m interface{}) (err error) {
ss.method,
"grpc.message",
ss.cfg.serviceName.String(),
ss.cfg.serviceSource,
ss.cfg.startSpanOptions(tracer.Measured())...,
)
span.SetTag(ext.Component, componentName)
Expand Down Expand Up @@ -93,6 +95,7 @@ func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
info.FullMethod,
cfg.spanName,
cfg.serviceName.String(),
cfg.serviceSource,
cfg.startSpanOptions(tracer.Measured(),
tracer.Tag(ext.Component, componentName),
tracer.Tag(ext.SpanKind, ext.SpanKindServer))...,
Expand Down Expand Up @@ -140,6 +143,7 @@ func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
info.FullMethod,
cfg.spanName,
cfg.serviceName.String(),
cfg.serviceSource,
cfg.startSpanOptions(tracer.Measured(),
tracer.Tag(ext.Component, componentName),
tracer.Tag(ext.SpanKind, ext.SpanKindServer))...,
Expand Down
1 change: 1 addition & 0 deletions contrib/google.golang.org/grpc/stats_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func (h *clientStatsHandler) TagRPC(ctx context.Context, rti *stats.RPCTagInfo)
rti.FullMethodName,
h.cfg.spanName,
h.cfg.serviceName.String(),
h.cfg.serviceSource,
spanOpts...,
)
ctx = injectSpanIntoContext(ctx)
Expand Down
2 changes: 2 additions & 0 deletions contrib/google.golang.org/grpc/stats_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/DataDog/dd-trace-go/v2/ddtrace/ext"
"github.com/DataDog/dd-trace-go/v2/ddtrace/mocktracer"
"github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
"github.com/DataDog/dd-trace-go/v2/instrumentation"

"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
Expand Down Expand Up @@ -60,6 +61,7 @@ func TestClientStatsHandler(t *testing.T) {
assert.Equal("grpc", tags[ext.RPCSystem])
assert.Equal("/grpc.Fixture/Ping", tags[ext.GRPCFullMethod])
assert.Equal(ext.SpanKindClient, tags[ext.SpanKind])
assert.Equal(instrumentation.ServiceSourceWithServiceOption, tags[ext.KeyServiceSource])
}

func newClientStatsHandlerTestServer(statsHandler stats.Handler) (*rig, error) {
Expand Down
1 change: 1 addition & 0 deletions contrib/google.golang.org/grpc/stats_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func (h *serverStatsHandler) TagRPC(ctx context.Context, rti *stats.RPCTagInfo)
rti.FullMethodName,
h.cfg.spanName,
h.cfg.serviceName.String(),
h.cfg.serviceSource,
spanOpts...,
)
return ctx
Expand Down
2 changes: 2 additions & 0 deletions contrib/google.golang.org/grpc/stats_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/DataDog/dd-trace-go/v2/ddtrace/ext"
"github.com/DataDog/dd-trace-go/v2/ddtrace/mocktracer"
"github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
"github.com/DataDog/dd-trace-go/v2/instrumentation"

"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
Expand Down Expand Up @@ -56,6 +57,7 @@ func TestServerStatsHandler(t *testing.T) {
assert.Equal("grpc", tags[ext.RPCSystem])
assert.Equal("/grpc.Fixture/Ping", tags[ext.GRPCFullMethod])
assert.Equal(ext.SpanKindServer, tags[ext.SpanKind])
assert.Equal(instrumentation.ServiceSourceWithServiceOption, tags[ext.KeyServiceSource])
}

func newServerStatsHandlerTestServer(statsHandler stats.Handler) (*rig, error) {
Expand Down
3 changes: 3 additions & 0 deletions contrib/redis/go-redis.v9/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

type clientConfig struct {
serviceName string
serviceSource string
spanName string
analyticsRate float64
skipRaw bool
Expand All @@ -34,6 +35,7 @@ func (fn ClientOptionFn) apply(cfg *clientConfig) {

func defaults(cfg *clientConfig) {
cfg.serviceName = instr.ServiceName(instrumentation.ComponentDefault, nil)
cfg.serviceSource = string(instrumentation.PackageRedisGoRedisV9)
cfg.spanName = instr.OperationName(instrumentation.ComponentDefault, nil)
cfg.analyticsRate = instr.AnalyticsRate(false)
cfg.skipRaw = !options.GetBoolEnv("DD_TRACE_REDIS_RAW_COMMAND", true)
Expand All @@ -53,6 +55,7 @@ func WithSkipRawCommand(skip bool) ClientOptionFn {
func WithService(name string) ClientOptionFn {
return func(cfg *clientConfig) {
cfg.serviceName = name
cfg.serviceSource = instrumentation.ServiceSourceWithServiceOption
}
}

Expand Down
Loading
Loading