///|
// Stretch an 8-byte wall-clock timestamp to 32 bytes using splitmix64-style
// mixing constants. Not cryptographically strong, but sufficient to prevent
// accidental trace-ID collisions between independently-launched processes.
// Two processes starting within the same nanosecond would still collide —
// for adversarial collision resistance, OS entropy would be needed, which
// moonbitlang/core/random does not currently expose.
fn make_seed() -> Bytes {
let t = @env.now()
let constants : Array[UInt64] = [
0UL, 0x9e3779b97f4a7c15UL, 0x6c62272e07bb0142UL, 0x94d049bb133111ebUL,
]
let arr : Array[Byte] = Array::make(32, b'\x00')
for seg in 0..<4 {
let v = t ^ constants[seg]
for i in 0..<8 {
arr[seg * 8 + i] = (v >> ((7 - i) * 8)).to_byte()
}
}
Bytes::from_array(arr[:])
}
///|
let rng : @random.Rand = @random.Rand::chacha8(seed=make_seed())
///|
fn to_hex_16(val : UInt64) -> String {
val.to_string(radix=16).pad_start(16, '0')
}
///|
pub fn next_trace_id() -> String {
let mut hi = rng.uint64()
let mut lo = rng.uint64()
// OTLP forbids all-zero trace IDs (probability 2^-128, checked for correctness)
while hi == 0UL && lo == 0UL {
hi = rng.uint64()
lo = rng.uint64()
}
to_hex_16(hi) + to_hex_16(lo)
}
///|
pub fn next_span_id() -> String {
let mut id = rng.uint64()
// OTLP forbids all-zero span IDs (probability 2^-64, checked for correctness)
while id == 0UL {
id = rng.uint64()
}
to_hex_16(id)
}