| // Copyright 2019 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package telemetry |
| |
| import ( |
| crand "crypto/rand" |
| "encoding/binary" |
| "fmt" |
| "math/rand" |
| "sync" |
| "sync/atomic" |
| ) |
| |
| type TraceID [16]byte |
| type SpanID [8]byte |
| |
| func (t TraceID) String() string { |
| return fmt.Sprintf("%02x", t[:]) |
| } |
| |
| func (s SpanID) String() string { |
| return fmt.Sprintf("%02x", s[:]) |
| } |
| |
| func (s SpanID) IsValid() bool { |
| return s != SpanID{} |
| } |
| |
| var ( |
| generationMu sync.Mutex |
| nextSpanID uint64 |
| spanIDInc uint64 |
| |
| traceIDAdd [2]uint64 |
| traceIDRand *rand.Rand |
| ) |
| |
| func initGenerator() { |
| var rngSeed int64 |
| for _, p := range []interface{}{ |
| &rngSeed, &traceIDAdd, &nextSpanID, &spanIDInc, |
| } { |
| binary.Read(crand.Reader, binary.LittleEndian, p) |
| } |
| traceIDRand = rand.New(rand.NewSource(rngSeed)) |
| spanIDInc |= 1 |
| } |
| |
| func NewTraceID() TraceID { |
| generationMu.Lock() |
| defer generationMu.Unlock() |
| if traceIDRand == nil { |
| initGenerator() |
| } |
| var tid [16]byte |
| binary.LittleEndian.PutUint64(tid[0:8], traceIDRand.Uint64()+traceIDAdd[0]) |
| binary.LittleEndian.PutUint64(tid[8:16], traceIDRand.Uint64()+traceIDAdd[1]) |
| return tid |
| } |
| |
| func NewSpanID() SpanID { |
| var id uint64 |
| for id == 0 { |
| id = atomic.AddUint64(&nextSpanID, spanIDInc) |
| } |
| var sid [8]byte |
| binary.LittleEndian.PutUint64(sid[:], id) |
| return sid |
| } |