From a564abf23ab3e0ec9fde8d97b97483b32afdfbbb Mon Sep 17 00:00:00 2001 From: Kyle Nusbaum Date: Tue, 7 Jul 2020 12:56:57 -0500 Subject: [PATCH 1/6] all: add runtime-id to profiler and tracer global tags. --- ddtrace/ext/tags.go | 3 +++ ddtrace/tracer/option.go | 1 + internal/globalconfig/globalconfig.go | 10 ++++++++++ profiler/options.go | 2 ++ 4 files changed, 16 insertions(+) diff --git a/ddtrace/ext/tags.go b/ddtrace/ext/tags.go index d6c44bf344..b9ab043a1f 100644 --- a/ddtrace/ext/tags.go +++ b/ddtrace/ext/tags.go @@ -82,4 +82,7 @@ const ( // ManualDrop is a tag which specifies that the trace to which this span // belongs to should be dropped when set to true. ManualDrop = "manual.drop" + + // RuntimeID is a tag that contains a unique id for this process. + RuntimeID = "runtime-id" ) diff --git a/ddtrace/tracer/option.go b/ddtrace/tracer/option.go index b42602ff32..181b3a9606 100644 --- a/ddtrace/tracer/option.go +++ b/ddtrace/tracer/option.go @@ -138,6 +138,7 @@ func newConfig(opts ...StartOption) *config { for _, fn := range opts { fn(c) } + WithGlobalTag(ext.RuntimeID, globalconfig.GetRuntimeID())(c) if c.env == "" { if v, ok := c.globalTags["env"]; ok { if e, ok := v.(string); ok { diff --git a/internal/globalconfig/globalconfig.go b/internal/globalconfig/globalconfig.go index 3dcef228e0..3efa1f7773 100644 --- a/internal/globalconfig/globalconfig.go +++ b/internal/globalconfig/globalconfig.go @@ -10,16 +10,20 @@ package globalconfig import ( "math" "sync" + + "github.com/google/uuid" ) var cfg = &config{ analyticsRate: math.NaN(), + runtimeID: uuid.New().String(), } type config struct { mu sync.RWMutex analyticsRate float64 serviceName string + runtimeID string } // AnalyticsRate returns the sampling rate at which events should be marked. It uses @@ -51,3 +55,9 @@ func SetServiceName(name string) { defer cfg.mu.Unlock() cfg.serviceName = name } + +func GetRuntimeID() string { + cfg.mu.RLock() + defer cfg.mu.RUnlock() + return cfg.runtimeID +} diff --git a/profiler/options.go b/profiler/options.go index 401dfc98c0..043bf720b9 100644 --- a/profiler/options.go +++ b/profiler/options.go @@ -15,6 +15,7 @@ import ( "strings" "time" + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" "gopkg.in/DataDog/dd-trace-go.v1/internal/version" @@ -131,6 +132,7 @@ func defaultConfig() *config { "runtime_compiler:"+runtime.Compiler, "runtime_arch:"+runtime.GOARCH, "runtime_os:"+runtime.GOOS, + "runtime-id:"+globalconfig.GetRuntimeID(), )(&c) // not for public use if v := os.Getenv("DD_PROFILING_URL"); v != "" { From 92827b5b165730751e2a47e147276f307bab816a Mon Sep 17 00:00:00 2001 From: Kyle Nusbaum Date: Tue, 7 Jul 2020 13:45:54 -0500 Subject: [PATCH 2/6] add tests for runtime id --- ddtrace/tracer/tracer_test.go | 2 ++ profiler/options_test.go | 2 ++ profiler/upload_test.go | 2 ++ 3 files changed, 6 insertions(+) diff --git a/ddtrace/tracer/tracer_test.go b/ddtrace/tracer/tracer_test.go index d7a6a4668f..d030da0abe 100644 --- a/ddtrace/tracer/tracer_test.go +++ b/ddtrace/tracer/tracer_test.go @@ -21,6 +21,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/internal" + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" "github.com/stretchr/testify/assert" @@ -190,6 +191,7 @@ func TestTracerStartSpan(t *testing.T) { // A span is not measured unless made so specifically _, ok := span.Meta[keyMeasured] assert.False(ok) + assert.Equal(globalconfig.GetRuntimeID(), span.Meta[ext.RuntimeID]) }) t.Run("priority", func(t *testing.T) { diff --git a/profiler/options_test.go b/profiler/options_test.go index 6ac0505a23..dc915dbda2 100644 --- a/profiler/options_test.go +++ b/profiler/options_test.go @@ -14,6 +14,7 @@ import ( "github.com/DataDog/datadog-go/statsd" "github.com/stretchr/testify/assert" + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" ) func TestOptions(t *testing.T) { @@ -242,6 +243,7 @@ func TestDefaultConfig(t *testing.T) { assert.Equal(DefaultDuration, cfg.cpuDuration) assert.Equal(DefaultMutexFraction, cfg.mutexFraction) assert.Equal(DefaultBlockRate, cfg.blockRate) + assert.Contains(cfg.tags, "runtime-id:"+globalconfig.GetRuntimeID()) }) } diff --git a/profiler/upload_test.go b/profiler/upload_test.go index e62552986d..c1fdd28896 100644 --- a/profiler/upload_test.go +++ b/profiler/upload_test.go @@ -20,6 +20,7 @@ import ( "testing" "time" + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" "gopkg.in/DataDog/dd-trace-go.v1/internal/version" "github.com/stretchr/testify/assert" @@ -75,6 +76,7 @@ func TestTryUpload(t *testing.T) { fmt.Sprintf("runtime_compiler:%s", runtime.Compiler), fmt.Sprintf("runtime_arch:%s", runtime.GOARCH), fmt.Sprintf("runtime_os:%s", runtime.GOOS), + fmt.Sprintf("runtime-id:%s", globalconfig.GetRuntimeID()), }, tags) for k, v := range map[string]string{ "format": "pprof", From a0aa3ac84587b8aeabfa6607f106f4217de098da Mon Sep 17 00:00:00 2001 From: Kyle Nusbaum Date: Tue, 7 Jul 2020 13:50:58 -0500 Subject: [PATCH 3/6] add documentation --- internal/globalconfig/globalconfig.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/globalconfig/globalconfig.go b/internal/globalconfig/globalconfig.go index 3efa1f7773..5394bd829a 100644 --- a/internal/globalconfig/globalconfig.go +++ b/internal/globalconfig/globalconfig.go @@ -56,6 +56,7 @@ func SetServiceName(name string) { cfg.serviceName = name } +// GetRuntimeID returns this process's unique runtime id. func GetRuntimeID() string { cfg.mu.RLock() defer cfg.mu.RUnlock() From 3c5c65396cbb25fb4f81c7d013ea7a6fa915a036 Mon Sep 17 00:00:00 2001 From: Kyle Nusbaum Date: Tue, 7 Jul 2020 15:45:40 -0500 Subject: [PATCH 4/6] test --- profiler/profile.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/profiler/profile.go b/profiler/profile.go index 35352f8106..9b8afcb28f 100644 --- a/profiler/profile.go +++ b/profiler/profile.go @@ -8,6 +8,7 @@ package profiler import ( "bytes" "errors" + "fmt" "io" "runtime/pprof" "time" @@ -29,6 +30,8 @@ const ( // MutexProfile reports the lock contentions. When you think your CPU is not fully utilized due // to a mutex contention, use this profile. Mutex profile is not enabled by default. MutexProfile + // GoroutineProfile reports stack traces of all current goroutines + GoroutineProfile ) func (t ProfileType) String() string { @@ -41,6 +44,8 @@ func (t ProfileType) String() string { return "mutex" case BlockProfile: return "block" + case GoroutineProfile: + return "goroutine" default: return "unknown" } @@ -75,6 +80,8 @@ func (p *profiler) runProfile(t ProfileType) (*profile, error) { return mutexProfile(p.cfg) case BlockProfile: return blockProfile(p.cfg) + case GoroutineProfile: + return goroutineProfile(p.cfg) default: return nil, errors.New("profile type not implemented") } @@ -162,6 +169,10 @@ func mutexProfile(cfg *config) (*profile, error) { }, nil } +func goroutineProfile(cfg *config) (*profile, error) { + return nil, fmt.Errorf("Goroutine profile not available yet.") +} + // now returns current time in UTC. func now() time.Time { return time.Now().UTC() From 71b7ce837363e4d72c1975f01a128bb013b519ba Mon Sep 17 00:00:00 2001 From: Kyle Nusbaum Date: Tue, 7 Jul 2020 15:50:04 -0500 Subject: [PATCH 5/6] rename GetRuntimeID and add not-empty test --- ddtrace/tracer/option.go | 2 +- ddtrace/tracer/tracer_test.go | 3 ++- internal/globalconfig/globalconfig.go | 4 ++-- profiler/options.go | 2 +- profiler/options_test.go | 2 +- profiler/upload_test.go | 2 +- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ddtrace/tracer/option.go b/ddtrace/tracer/option.go index 181b3a9606..ecaed28918 100644 --- a/ddtrace/tracer/option.go +++ b/ddtrace/tracer/option.go @@ -138,7 +138,7 @@ func newConfig(opts ...StartOption) *config { for _, fn := range opts { fn(c) } - WithGlobalTag(ext.RuntimeID, globalconfig.GetRuntimeID())(c) + WithGlobalTag(ext.RuntimeID, globalconfig.RuntimeID())(c) if c.env == "" { if v, ok := c.globalTags["env"]; ok { if e, ok := v.(string); ok { diff --git a/ddtrace/tracer/tracer_test.go b/ddtrace/tracer/tracer_test.go index d030da0abe..98f14c46e2 100644 --- a/ddtrace/tracer/tracer_test.go +++ b/ddtrace/tracer/tracer_test.go @@ -191,7 +191,8 @@ func TestTracerStartSpan(t *testing.T) { // A span is not measured unless made so specifically _, ok := span.Meta[keyMeasured] assert.False(ok) - assert.Equal(globalconfig.GetRuntimeID(), span.Meta[ext.RuntimeID]) + assert.Equal(globalconfig.RuntimeID(), span.Meta[ext.RuntimeID]) + assert.NotEqual("", span.Meta[ext.RuntimeID]) }) t.Run("priority", func(t *testing.T) { diff --git a/internal/globalconfig/globalconfig.go b/internal/globalconfig/globalconfig.go index 5394bd829a..2a83b97ba6 100644 --- a/internal/globalconfig/globalconfig.go +++ b/internal/globalconfig/globalconfig.go @@ -56,8 +56,8 @@ func SetServiceName(name string) { cfg.serviceName = name } -// GetRuntimeID returns this process's unique runtime id. -func GetRuntimeID() string { +// RuntimeID returns this process's unique runtime id. +func RuntimeID() string { cfg.mu.RLock() defer cfg.mu.RUnlock() return cfg.runtimeID diff --git a/profiler/options.go b/profiler/options.go index 043bf720b9..fba5afebe6 100644 --- a/profiler/options.go +++ b/profiler/options.go @@ -132,7 +132,7 @@ func defaultConfig() *config { "runtime_compiler:"+runtime.Compiler, "runtime_arch:"+runtime.GOARCH, "runtime_os:"+runtime.GOOS, - "runtime-id:"+globalconfig.GetRuntimeID(), + "runtime-id:"+globalconfig.RuntimeID(), )(&c) // not for public use if v := os.Getenv("DD_PROFILING_URL"); v != "" { diff --git a/profiler/options_test.go b/profiler/options_test.go index dc915dbda2..bcbdda4d8f 100644 --- a/profiler/options_test.go +++ b/profiler/options_test.go @@ -243,7 +243,7 @@ func TestDefaultConfig(t *testing.T) { assert.Equal(DefaultDuration, cfg.cpuDuration) assert.Equal(DefaultMutexFraction, cfg.mutexFraction) assert.Equal(DefaultBlockRate, cfg.blockRate) - assert.Contains(cfg.tags, "runtime-id:"+globalconfig.GetRuntimeID()) + assert.Contains(cfg.tags, "runtime-id:"+globalconfig.RuntimeID()) }) } diff --git a/profiler/upload_test.go b/profiler/upload_test.go index c1fdd28896..737cef9bd4 100644 --- a/profiler/upload_test.go +++ b/profiler/upload_test.go @@ -76,7 +76,7 @@ func TestTryUpload(t *testing.T) { fmt.Sprintf("runtime_compiler:%s", runtime.Compiler), fmt.Sprintf("runtime_arch:%s", runtime.GOARCH), fmt.Sprintf("runtime_os:%s", runtime.GOOS), - fmt.Sprintf("runtime-id:%s", globalconfig.GetRuntimeID()), + fmt.Sprintf("runtime-id:%s", globalconfig.RuntimeID()), }, tags) for k, v := range map[string]string{ "format": "pprof", From 7ac441bcb9d914cafd6573ab968961b5cbf2bba2 Mon Sep 17 00:00:00 2001 From: Kyle Nusbaum Date: Tue, 7 Jul 2020 15:53:08 -0500 Subject: [PATCH 6/6] fix profiler --- profiler/profile.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/profiler/profile.go b/profiler/profile.go index 9b8afcb28f..35352f8106 100644 --- a/profiler/profile.go +++ b/profiler/profile.go @@ -8,7 +8,6 @@ package profiler import ( "bytes" "errors" - "fmt" "io" "runtime/pprof" "time" @@ -30,8 +29,6 @@ const ( // MutexProfile reports the lock contentions. When you think your CPU is not fully utilized due // to a mutex contention, use this profile. Mutex profile is not enabled by default. MutexProfile - // GoroutineProfile reports stack traces of all current goroutines - GoroutineProfile ) func (t ProfileType) String() string { @@ -44,8 +41,6 @@ func (t ProfileType) String() string { return "mutex" case BlockProfile: return "block" - case GoroutineProfile: - return "goroutine" default: return "unknown" } @@ -80,8 +75,6 @@ func (p *profiler) runProfile(t ProfileType) (*profile, error) { return mutexProfile(p.cfg) case BlockProfile: return blockProfile(p.cfg) - case GoroutineProfile: - return goroutineProfile(p.cfg) default: return nil, errors.New("profile type not implemented") } @@ -169,10 +162,6 @@ func mutexProfile(cfg *config) (*profile, error) { }, nil } -func goroutineProfile(cfg *config) (*profile, error) { - return nil, fmt.Errorf("Goroutine profile not available yet.") -} - // now returns current time in UTC. func now() time.Time { return time.Now().UTC()