package alert import ( "crypto/rand" "encoding/hex" "sync/atomic" "time" ) // ulidLike returns a 26-char time-sortable ID. Layout: // - first 10 hex chars: unix ms (fits in 40 bits, padded) // - next 16 hex chars: random // Not a real ULID, but good enough for log ordering and broker keys. func ulidLike() string { now := time.Now().UTC().UnixMilli() var msBuf [8]byte for i := 7; i >= 0; i-- { msBuf[i] = byte(now) now >>= 8 } var rnd [8]byte if _, err := rand.Read(rnd[:]); err != nil { // crypto/rand should never fail; if it does, fall back to atomic counter // so we still produce a unique ID. fb := atomic.AddUint64(&fallbackCounter, 1) for i := 7; i >= 0; i-- { rnd[i] = byte(fb) fb >>= 8 } } return hex.EncodeToString(msBuf[:])[:10] + hex.EncodeToString(rnd[:]) } var fallbackCounter uint64