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: use math/rand/v2 for SpanID and TraceID #2689

Merged
merged 4 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions ddtrace/tracer/rand.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016 Datadog, Inc.

//go:build !go1.22

// TODO(knusbaum): This file should be deleted once go1.21 falls out of support
package tracer

import (
Expand Down Expand Up @@ -54,3 +57,14 @@ func (rs *safeSource) Seed(seed int64) {
rs.source.Seed(seed)
rs.Unlock()
}

// generateSpanID returns a random uint64 that has been XORd with the startTime.
// This is done to get around the 32-bit random seed limitation that may create collisions if there is a large number
// of go services all generating spans.
func generateSpanID(startTime int64) uint64 {
return random.Uint64() ^ uint64(startTime)
}

func randUint64() uint64 {
return random.Uint64()
}
21 changes: 21 additions & 0 deletions ddtrace/tracer/rand_go1_22.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016 Datadog, Inc.

//go:build go1.22

package tracer

import (
"math"
"math/rand/v2"
)

func randUint64() uint64 {
return rand.Uint64()
}

func generateSpanID(startTime int64) uint64 {
return rand.Uint64() & math.MaxInt64
}
4 changes: 2 additions & 2 deletions ddtrace/tracer/sampler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,12 +442,12 @@ func TestRuleEnvVars(t *testing.T) {

func TestRulesSampler(t *testing.T) {
makeSpan := func(op string, svc string) *span {
s := newSpan(op, svc, "res-10", random.Uint64(), random.Uint64(), 0)
s := newSpan(op, svc, "res-10", randUint64(), randUint64(), 0)
s.setMeta("hostname", "hn-30")
return s
}
makeFinishedSpan := func(op, svc, resource string, tags map[string]interface{}) *span {
s := newSpan(op, svc, resource, random.Uint64(), random.Uint64(), 0)
s := newSpan(op, svc, resource, randUint64(), randUint64(), 0)
for k, v := range tags {
s.SetTag(k, v)
}
Expand Down
6 changes: 3 additions & 3 deletions ddtrace/tracer/spancontext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func TestSpanTracePushOne(t *testing.T) {
_, transport, flush, stop := startTestTracer(t)
defer stop()

traceID := random.Uint64()
traceID := randUint64()
root := newSpan("name1", "a-service", "a-resource", traceID, traceID, 0)
trace := root.context.trace

Expand Down Expand Up @@ -229,7 +229,7 @@ func TestSpanTracePushNoFinish(t *testing.T) {
assert.NotNil(buffer)
assert.Len(buffer.spans, 0)

traceID := random.Uint64()
traceID := randUint64()
root := newSpan("name1", "a-service", "a-resource", traceID, traceID, 0)
root.context.trace = buffer

Expand All @@ -254,7 +254,7 @@ func TestSpanTracePushSeveral(t *testing.T) {
assert.NotNil(buffer)
assert.Len(buffer.spans, 0)

traceID := random.Uint64()
traceID := randUint64()
root := trc.StartSpan("name1", WithSpanID(traceID))
span2 := trc.StartSpan("name2", ChildOf(root.Context()))
span3 := trc.StartSpan("name3", ChildOf(root.Context()))
Expand Down
7 changes: 0 additions & 7 deletions ddtrace/tracer/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,13 +610,6 @@ func (t *tracer) StartSpan(operationName string, options ...ddtrace.StartSpanOpt
return span
}

// generateSpanID returns a random uint64 that has been XORd with the startTime.
// This is done to get around the 32-bit random seed limitation that may create collisions if there is a large number
// of go services all generating spans.
func generateSpanID(startTime int64) uint64 {
return random.Uint64() ^ uint64(startTime)
}

// applyPPROFLabels applies pprof labels for the profiler's code hotspots and
// endpoint filtering feature to span. When span finishes, any pprof labels
// found in ctx are restored. Additionally, this func informs the profiler how
Expand Down
38 changes: 38 additions & 0 deletions ddtrace/tracer/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,44 @@ func BenchmarkStartSpan(b *testing.B) {
}
}

func BenchmarkStartSpanConcurrent(b *testing.B) {
tracer, _, _, stop := startTestTracer(b, WithLogger(log.DiscardLogger{}), WithSampler(NewRateSampler(0)))
defer stop()

var wg sync.WaitGroup
var wgready sync.WaitGroup
start := make(chan struct{})
for i := 0; i < 10; i++ {
wg.Add(1)
wgready.Add(1)
go func() {
defer wg.Done()
root := tracer.StartSpan("pylons.request", ServiceName("pylons"), ResourceName("/"))
ctx := ContextWithSpan(context.TODO(), root)
wgready.Done()
<-start
for n := 0; n < b.N; n++ {
s, ok := SpanFromContext(ctx)
if !ok {
b.Fatal("no span")
}
StartSpan("op", ChildOf(s.Context()))
}
}()
}
wgready.Wait()
b.ResetTimer()
close(start)
wg.Wait()
}

func BenchmarkGenSpanID(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
generateSpanID(0)
}
}

// startTestTracer returns a Tracer with a DummyTransport
func startTestTracer(t testing.TB, opts ...StartOption) (trc *tracer, transport *dummyTransport, flush func(n int), stop func()) {
transport = newDummyTransport()
Expand Down
2 changes: 1 addition & 1 deletion ddtrace/tracer/writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestImplementsTraceWriter(t *testing.T) {

// makeSpan returns a span, adding n entries to meta and metrics each.
func makeSpan(n int) *span {
s := newSpan("encodeName", "encodeService", "encodeResource", random.Uint64(), random.Uint64(), random.Uint64())
s := newSpan("encodeName", "encodeService", "encodeResource", randUint64(), randUint64(), randUint64())
for i := 0; i < n; i++ {
istr := fmt.Sprintf("%0.10d", i)
s.Meta[istr] = istr
Expand Down
Loading