43 lines
1.1 KiB
Go
43 lines
1.1 KiB
Go
package controlapi
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/rand"
|
||
|
|
"encoding/hex"
|
||
|
|
"errors"
|
||
|
|
"math/big"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
const crockford = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
|
||
|
|
|
||
|
|
func newULID(prefix string, now time.Time) (string, error) {
|
||
|
|
value := make([]byte, 16)
|
||
|
|
milliseconds := uint64(now.UTC().UnixMilli())
|
||
|
|
value[0] = byte(milliseconds >> 40)
|
||
|
|
value[1] = byte(milliseconds >> 32)
|
||
|
|
value[2] = byte(milliseconds >> 24)
|
||
|
|
value[3] = byte(milliseconds >> 16)
|
||
|
|
value[4] = byte(milliseconds >> 8)
|
||
|
|
value[5] = byte(milliseconds)
|
||
|
|
if _, err := rand.Read(value[6:]); err != nil {
|
||
|
|
return "", errors.New("generate identifier randomness")
|
||
|
|
}
|
||
|
|
number := new(big.Int).SetBytes(value)
|
||
|
|
base := big.NewInt(32)
|
||
|
|
remainder := new(big.Int)
|
||
|
|
encoded := make([]byte, 26)
|
||
|
|
for index := len(encoded) - 1; index >= 0; index-- {
|
||
|
|
number.QuoRem(number, base, remainder)
|
||
|
|
encoded[index] = crockford[remainder.Int64()]
|
||
|
|
}
|
||
|
|
return prefix + string(encoded), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newTraceID() (string, error) {
|
||
|
|
value := make([]byte, 16)
|
||
|
|
if _, err := rand.Read(value); err != nil {
|
||
|
|
return "", errors.New("generate trace identifier")
|
||
|
|
}
|
||
|
|
return "trace_" + hex.EncodeToString(value), nil
|
||
|
|
}
|