idgenerator.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright 2022 The OpenZipkin Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /*
  15. Package idgenerator contains several Span and Trace ID generators which can be
  16. used by the Zipkin tracer. Additional third party generators can be plugged in
  17. if they adhere to the IDGenerator interface.
  18. */
  19. package idgenerator
  20. import (
  21. "math/rand"
  22. "sync"
  23. "time"
  24. "github.com/openzipkin/zipkin-go/model"
  25. )
  26. var (
  27. seededIDGen = rand.New(rand.NewSource(time.Now().UnixNano()))
  28. // NewSource returns a new pseudo-random Source seeded with the given value.
  29. // Unlike the default Source used by top-level functions, this source is not
  30. // safe for concurrent use by multiple goroutines. Hence the need for a mutex.
  31. seededIDLock sync.Mutex
  32. )
  33. // IDGenerator interface can be used to provide the Zipkin Tracer with custom
  34. // implementations to generate Span and Trace IDs.
  35. type IDGenerator interface {
  36. SpanID(traceID model.TraceID) model.ID // Generates a new Span ID
  37. TraceID() model.TraceID // Generates a new Trace ID
  38. }
  39. // NewRandom64 returns an ID Generator which can generate 64 bit trace and span
  40. // id's
  41. func NewRandom64() IDGenerator {
  42. return &randomID64{}
  43. }
  44. // NewRandom128 returns an ID Generator which can generate 128 bit trace and 64
  45. // bit span id's
  46. func NewRandom128() IDGenerator {
  47. return &randomID128{}
  48. }
  49. // NewRandomTimestamped generates 128 bit time sortable traceid's and 64 bit
  50. // spanid's.
  51. func NewRandomTimestamped() IDGenerator {
  52. return &randomTimestamped{}
  53. }
  54. // randomID64 can generate 64 bit traceid's and 64 bit spanid's.
  55. type randomID64 struct{}
  56. func (r *randomID64) TraceID() (id model.TraceID) {
  57. seededIDLock.Lock()
  58. id = model.TraceID{
  59. Low: uint64(seededIDGen.Int63()),
  60. }
  61. seededIDLock.Unlock()
  62. return
  63. }
  64. func (r *randomID64) SpanID(traceID model.TraceID) (id model.ID) {
  65. if !traceID.Empty() {
  66. return model.ID(traceID.Low)
  67. }
  68. seededIDLock.Lock()
  69. id = model.ID(seededIDGen.Int63())
  70. seededIDLock.Unlock()
  71. return
  72. }
  73. // randomID128 can generate 128 bit traceid's and 64 bit spanid's.
  74. type randomID128 struct{}
  75. func (r *randomID128) TraceID() (id model.TraceID) {
  76. seededIDLock.Lock()
  77. id = model.TraceID{
  78. High: uint64(seededIDGen.Int63()),
  79. Low: uint64(seededIDGen.Int63()),
  80. }
  81. seededIDLock.Unlock()
  82. return
  83. }
  84. func (r *randomID128) SpanID(traceID model.TraceID) (id model.ID) {
  85. if !traceID.Empty() {
  86. return model.ID(traceID.Low)
  87. }
  88. seededIDLock.Lock()
  89. id = model.ID(seededIDGen.Int63())
  90. seededIDLock.Unlock()
  91. return
  92. }
  93. // randomTimestamped can generate 128 bit time sortable traceid's compatible
  94. // with AWS X-Ray and 64 bit spanid's.
  95. type randomTimestamped struct{}
  96. func (t *randomTimestamped) TraceID() (id model.TraceID) {
  97. seededIDLock.Lock()
  98. id = model.TraceID{
  99. High: uint64(time.Now().Unix()<<32) + uint64(seededIDGen.Int31()),
  100. Low: uint64(seededIDGen.Int63()),
  101. }
  102. seededIDLock.Unlock()
  103. return
  104. }
  105. func (t *randomTimestamped) SpanID(traceID model.TraceID) (id model.ID) {
  106. if !traceID.Empty() {
  107. return model.ID(traceID.Low)
  108. }
  109. seededIDLock.Lock()
  110. id = model.ID(seededIDGen.Int63())
  111. seededIDLock.Unlock()
  112. return
  113. }