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  }