github.com/v2fly/tools@v0.100.0/internal/event/export/id.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package export 6 7 import ( 8 crand "crypto/rand" 9 "encoding/binary" 10 "fmt" 11 "math/rand" 12 "sync" 13 "sync/atomic" 14 ) 15 16 type TraceID [16]byte 17 type SpanID [8]byte 18 19 func (t TraceID) String() string { 20 return fmt.Sprintf("%02x", t[:]) 21 } 22 23 func (s SpanID) String() string { 24 return fmt.Sprintf("%02x", s[:]) 25 } 26 27 func (s SpanID) IsValid() bool { 28 return s != SpanID{} 29 } 30 31 var ( 32 generationMu sync.Mutex 33 nextSpanID uint64 34 spanIDInc uint64 35 36 traceIDAdd [2]uint64 37 traceIDRand *rand.Rand 38 ) 39 40 func initGenerator() { 41 var rngSeed int64 42 for _, p := range []interface{}{ 43 &rngSeed, &traceIDAdd, &nextSpanID, &spanIDInc, 44 } { 45 binary.Read(crand.Reader, binary.LittleEndian, p) 46 } 47 traceIDRand = rand.New(rand.NewSource(rngSeed)) 48 spanIDInc |= 1 49 } 50 51 func newTraceID() TraceID { 52 generationMu.Lock() 53 defer generationMu.Unlock() 54 if traceIDRand == nil { 55 initGenerator() 56 } 57 var tid [16]byte 58 binary.LittleEndian.PutUint64(tid[0:8], traceIDRand.Uint64()+traceIDAdd[0]) 59 binary.LittleEndian.PutUint64(tid[8:16], traceIDRand.Uint64()+traceIDAdd[1]) 60 return tid 61 } 62 63 func newSpanID() SpanID { 64 var id uint64 65 for id == 0 { 66 id = atomic.AddUint64(&nextSpanID, spanIDInc) 67 } 68 var sid [8]byte 69 binary.LittleEndian.PutUint64(sid[:], id) 70 return sid 71 }