Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ddtrace/tracer: add service version to tracer. #607

Merged
merged 13 commits into from
Mar 18, 2020
17 changes: 8 additions & 9 deletions contrib/google.golang.org/grpc/stats_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,14 @@ func TestClientStatsHandler(t *testing.T) {
assert.NotZero(span.StartTime())
assert.True(span.FinishTime().After(span.StartTime()))
assert.Equal("grpc.client", span.OperationName())
assert.Equal(map[string]interface{}{
"span.type": ext.AppTypeRPC,
"grpc.code": codes.OK.String(),
"service.name": serviceName,
"resource.name": "/grpc.Fixture/Ping",
tagMethodName: "/grpc.Fixture/Ping",
ext.TargetHost: "127.0.0.1",
ext.TargetPort: server.port,
}, span.Tags())
tags := span.Tags()
assert.Equal(ext.AppTypeRPC, tags["span.type"])
assert.Equal(codes.OK.String(), tags["grpc.code"])
assert.Equal(serviceName, tags["service.name"])
assert.Equal("/grpc.Fixture/Ping", tags["resource.name"])
assert.Equal("/grpc.Fixture/Ping", tags[tagMethodName])
assert.Equal("127.0.0.1", tags[ext.TargetHost])
assert.Equal(server.port, tags[ext.TargetPort])
}

func newClientStatsHandlerTestServer(statsHandler stats.Handler) (*rig, error) {
Expand Down
15 changes: 7 additions & 8 deletions contrib/google.golang.org/grpc/stats_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,13 @@ func TestServerStatsHandler(t *testing.T) {
assert.NotZero(span.StartTime())
assert.True(span.FinishTime().After(span.StartTime()))
assert.Equal("grpc.server", span.OperationName())
assert.Equal(map[string]interface{}{
"span.type": ext.AppTypeRPC,
"grpc.code": codes.OK.String(),
"service.name": serviceName,
"resource.name": "/grpc.Fixture/Ping",
tagMethodName: "/grpc.Fixture/Ping",
"_dd.measured": 1,
}, span.Tags())
tags := span.Tags()
assert.Equal(ext.AppTypeRPC, tags["span.type"])
assert.Equal(codes.OK.String(), tags["grpc.code"])
assert.Equal(serviceName, tags["service.name"])
assert.Equal("/grpc.Fixture/Ping", tags["resource.name"])
assert.Equal("/grpc.Fixture/Ping", tags[tagMethodName])
assert.Equal(1, tags["_dd.measured"])
}

func newServerStatsHandlerTestServer(statsHandler stats.Handler) (*rig, error) {
Expand Down
3 changes: 3 additions & 0 deletions ddtrace/ext/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ const (
// ServiceName defines the Service name for this Span.
ServiceName = "service.name"

// Version is a tag that specifies the current application version.
Version = "version"

// ResourceName defines the Resource name for the Span.
ResourceName = "resource.name"

Expand Down
14 changes: 14 additions & 0 deletions ddtrace/tracer/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ type config struct {
// serviceName specifies the name of this application.
serviceName string

// version specifies the version of this application
version string

// sampler specifies the sampler that will be used for sampling traces.
sampler Sampler

Expand Down Expand Up @@ -110,6 +113,9 @@ func defaults(c *config) {
} else {
c.serviceName = filepath.Base(os.Args[0])
}
if ver := os.Getenv("DD_VERSION"); ver != "" {
c.version = ver
}
if v := os.Getenv("DD_TAGS"); v != "" {
for _, tag := range strings.Split(v, ",") {
tag = strings.TrimSpace(tag)
Expand Down Expand Up @@ -283,6 +289,14 @@ func WithSamplingRules(rules []SamplingRule) StartOption {
}
}

// WithServiceVersion specifies the version of the service that is running. This will
// be included in spans from this service in the "version" tag.
func WithServiceVersion(version string) StartOption {
return func(cfg *config) {
cfg.version = version
}
}

// StartSpanOption is a configuration option for StartSpan. It is aliased in order
// to help godoc group all the functions returning it together. It is considered
// more correct to refer to it as the type as the origin, ddtrace.StartSpanOption.
Expand Down
3 changes: 3 additions & 0 deletions ddtrace/tracer/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ func (t *tracer) StartSpan(operationName string, options ...ddtrace.StartSpanOpt
for k, v := range t.config.globalTags {
span.SetTag(k, v)
}
if t.config.version != "" && span.Service == t.config.serviceName {
span.SetTag(ext.Version, t.config.version)
}
if context == nil {
// this is a brand new trace, sample it
t.sample(span)
Expand Down
87 changes: 87 additions & 0 deletions ddtrace/tracer/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,93 @@ func TestTracerReportsHostname(t *testing.T) {
})
}

func TestEnvTags(t *testing.T) {
t.Run("service", func(t *testing.T) {
os.Setenv("DD_SERVICE", "servenv")
defer os.Unsetenv("DD_SERVICE")

tracer, _, _, stop := startTestTracer(t)
defer stop()

assert := assert.New(t)
sp := tracer.StartSpan("http.request").(*span)
assert.Equal("servenv", sp.Service)
})

t.Run("version", func(t *testing.T) {
os.Setenv("DD_VERSION", "1.2.3")
defer os.Unsetenv("DD_VERSION")

tracer, _, _, stop := startTestTracer(t)
defer stop()

assert := assert.New(t)
sp := tracer.StartSpan("http.request").(*span)
v := sp.Meta[ext.Version]
assert.Equal("1.2.3", v)
knusbaum marked this conversation as resolved.
Show resolved Hide resolved
})

t.Run("noversion", func(t *testing.T) {
os.Setenv("DD_VERSION", "1.2.3")
defer os.Unsetenv("DD_VERSION")

tracer, _, _, stop := startTestTracer(t, WithService("servenv"))
defer stop()

assert := assert.New(t)
sp := tracer.StartSpan("http.request", ServiceName("otherservenv")).(*span)
_, ok := sp.Meta[ext.Version]
assert.False(ok)
})

t.Run("noversion2", func(t *testing.T) {
knusbaum marked this conversation as resolved.
Show resolved Hide resolved
os.Setenv("DD_SERVICE", "servenv")
os.Setenv("DD_VERSION", "1.2.3")
defer os.Unsetenv("DD_VERSION")
defer os.Unsetenv("DD_SERVICE")

tracer, _, _, stop := startTestTracer(t)
defer stop()

assert := assert.New(t)
sp := tracer.StartSpan("http.request", ServiceName("otherservenv")).(*span)
_, ok := sp.Meta[ext.Version]
assert.False(ok)
})

t.Run("noversion3", func(t *testing.T) {
os.Setenv("DD_SERVICE", "servenv")
os.Setenv("DD_VERSION", "1.2.3")
defer os.Unsetenv("DD_VERSION")
knusbaum marked this conversation as resolved.
Show resolved Hide resolved
defer os.Unsetenv("DD_SERVICE")

// WithGlobalTag sets ext.ServiceName on each individual span, so version will not be set.
tracer, _, _, stop := startTestTracer(t, WithGlobalTag(ext.ServiceName, "otherservenv"))
defer stop()

assert := assert.New(t)
sp := tracer.StartSpan("http.request").(*span)
_, ok := sp.Meta[ext.Version]
assert.False(ok)
})

t.Run("serviceOverride", func(t *testing.T) {
knusbaum marked this conversation as resolved.
Show resolved Hide resolved
os.Setenv("DD_SERVICE", "servenv")
os.Setenv("DD_VERSION", "1.2.3")
defer os.Unsetenv("DD_VERSION")
defer os.Unsetenv("DD_SERVICE")

tracer, _, _, stop := startTestTracer(t, WithService("otherservenv"))
defer stop()

assert := assert.New(t)
sp := tracer.StartSpan("http.request").(*span)
assert.Equal("otherservenv", sp.Service)
v := sp.Meta[ext.Version]
assert.Equal("1.2.3", v)
})
}

// BenchmarkConcurrentTracing tests the performance of spawning a lot of
// goroutines where each one creates a trace with a parent and a child.
func BenchmarkConcurrentTracing(b *testing.B) {
Expand Down