Skip to content
This repository has been archived by the owner on Oct 3, 2023. It is now read-only.

new xray id generator #40

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions xray.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ package aws

import (
"context"
crand "crypto/rand"
"encoding/binary"
"fmt"
"io"
"io/ioutil"
"log"
"math/rand"
"net/http"
"os"
"regexp"
"sync"
"sync/atomic"
"time"

"github.com/aws/aws-sdk-go/aws"
Expand Down Expand Up @@ -465,3 +469,66 @@ func (e *Exporter) makeSegment(span *trace.SpanData) segment {

return s
}

type xrayIDGenerator struct {
sync.Mutex

// Please keep these as the first fields
// so that these 8 byte fields will be aligned on addresses
// divisible by 8, on both 32-bit and 64-bit machines when
// performing atomic increments and accesses.
// See:
// * https://github.com/census-instrumentation/opencensus-go/issues/587
// * https://github.com/census-instrumentation/opencensus-go/issues/865
// * https://golang.org/pkg/sync/atomic/#pkg-note-BUG
nextSpanID uint64
spanIDInc uint64

traceIDAdd [2]uint64
traceIDRand *rand.Rand
}

func NewIDGenerator() *xrayIDGenerator {
gen := &xrayIDGenerator{}
// initialize traceID and spanID generators.

var rngSeed int64
for _, p := range []interface{}{
&rngSeed, &gen.traceIDAdd, &gen.nextSpanID, &gen.spanIDInc,
} {
binary.Read(crand.Reader, binary.LittleEndian, p)
}
gen.traceIDRand = rand.New(rand.NewSource(rngSeed))
gen.spanIDInc |= 1

return gen

}

// NewSpanID returns a non-zero span ID from a randomly-chosen sequence.
func (gen *xrayIDGenerator) NewSpanID() [8]byte {
var id uint64
for id == 0 {
id = atomic.AddUint64(&gen.nextSpanID, gen.spanIDInc)
}
var sid [8]byte
binary.LittleEndian.PutUint64(sid[:], id)
return sid
}

// NewTraceID returns a non-zero trace ID from a randomly-chosen sequence.
// mu should be held while this function is called. convertToAmazonTraceID
// expects first 4 bytes to be current unix timestamp
func (gen *xrayIDGenerator) NewTraceID() [16]byte {
var tid [16]byte
// Construct the trace ID from two outputs of traceIDRand, with a constant
// added to each half for additional entropy.
gen.Lock()

binary.BigEndian.PutUint32(tid[0:4], uint32(time.Now().Unix()))
binary.BigEndian.PutUint32(tid[4:8], gen.traceIDRand.Uint32())
binary.BigEndian.PutUint64(tid[8:16], gen.traceIDRand.Uint64()+gen.traceIDAdd[1])

gen.Unlock()
return tid
}
15 changes: 15 additions & 0 deletions xray_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,3 +565,18 @@ func TestLookupRegionFromMetaData(t *testing.T) {
})
}
}

func TestIDGenerator(t *testing.T) {
gen := NewIDGenerator()

sid := gen.NewSpanID()
tid := gen.NewTraceID()

if len(sid) != 8 {
t.Errorf("span id wrong length; want 8, got %d", len(sid))
}

if len(tid) != 16 {
t.Errorf("span id wrong length; want 16, got %d", len(tid))
}
}