ddtrace/tracer: use math/rand/v2 for SpanID and TraceID #2689
+79
−13
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
With the new version 2 of the math/rand standard library package, there is no longer a need to perform our own complicated initialization of an RNG, and in fact, we should avoid doing so.
See more details about the new rand package here: https://go.dev/blog/randv2
Instead, we can rely on the global RNG provided by the Go runtime. We previously chose not to do that because we could not rely on the global RNG to be initialized, meaning there would likely be many trace and span ID clashes. Likewise, it was a bad idea to initialize the RNG ourselves, since as a library it's bad practice to mutate global state in a way that will have visible effects on the application.
We previously chose to initialize our own RNG instance for the tracer and synchronize access to it. Due to the low entropy of the RNG seed (it only used 32 bits of the 64 provided) we also chose to xor the produced random numbers with the current unix time in order to decrease collisions.
math/rand/v2 removes the need to do either of those things. The new global RNG is automatically seeded at startup with enough entropy to remove the need to xor with a timestamp. It also has the added benefit of being per-goroutine, meaning there is no synchronization involved.
This PR adds a new implementation of the span/trace ID generator which will be used for all Go applications compiled with go1.22.0 and later. The old implementation remains for older versions of Go, but should be removed once those versions fall out of the support window.
I've also added some benchmarks and used them to compare the old and new implementations.
The benefits of this change are a smaller implementation and less historical baggage, as well as improved performance if there are lots of threads trying to generate spans.
Motivation
Unsure? Have a question? Request a review!