1package ext
2
3import (
4	"fmt"
5	"math/rand"
6	"sync"
7	"time"
8)
9
10var r = rand.New(&lockedSource{src: rand.NewSource(time.Now().Unix())})
11
12// RandId creates a random identifier of the requested length.
13// Useful for assigning mostly-unique identifiers for logging
14// and identification that are unlikely to collide because of
15// short lifespan or low set cardinality
16func RandId(idlen int) string {
17	b := make([]byte, idlen)
18	var randVal uint32
19	for i := 0; i < idlen; i++ {
20		byteIdx := i % 4
21		if byteIdx == 0 {
22			randVal = r.Uint32()
23		}
24		b[i] = byte((randVal >> (8 * uint(byteIdx))) & 0xFF)
25	}
26	return fmt.Sprintf("%x", b)
27}
28
29// lockedSource is a wrapper to allow a rand.Source to be used
30// concurrently (same type as the one used internally in math/rand).
31type lockedSource struct {
32	lk  sync.Mutex
33	src rand.Source
34}
35
36func (r *lockedSource) Int63() (n int64) {
37	r.lk.Lock()
38	n = r.src.Int63()
39	r.lk.Unlock()
40	return
41}
42
43func (r *lockedSource) Seed(seed int64) {
44	r.lk.Lock()
45	r.src.Seed(seed)
46	r.lk.Unlock()
47}
48