summaryrefslogtreecommitdiffstats
path: root/server/src/trace.cppm
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/trace.cppm')
-rw-r--r--server/src/trace.cppm120
1 files changed, 65 insertions, 55 deletions
diff --git a/server/src/trace.cppm b/server/src/trace.cppm
index 00ecd05..35d32f3 100644
--- a/server/src/trace.cppm
+++ b/server/src/trace.cppm
@@ -11,69 +11,79 @@ import :util;
11 11
12namespace routemon::trace { 12namespace routemon::trace {
13 13
14 class uuid7 { 14class uuid7
15 std::uint64_t high_ = 0; 15{
16 std::uint64_t low_ = 0; 16 std::uint64_t high_ = 0;
17 std::uint64_t low_ = 0;
17 18
18 public: 19public:
19 uuid7() { 20 uuid7()
20 namespace chrono = std::chrono; 21 {
21 auto const unix_time_ms_signed = static_cast<std::int64_t>(chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count()); 22 namespace chrono = std::chrono;
22 if (unix_time_ms_signed < 0) 23 auto const unix_time_ms_signed = static_cast<std::int64_t>(
23 throw std::runtime_error{"system time before UNIX epoch"}; 24 chrono::duration_cast<chrono::milliseconds>(
24 auto const unix_time_ms = static_cast<std::uint64_t>(unix_time_ms_signed); 25 chrono::system_clock::now().time_since_epoch())
25 if (std::countl_zero(unix_time_ms) < 16) 26 .count());
26 throw std::runtime_error{"system time too great"}; 27 if (unix_time_ms_signed < 0)
28 throw std::runtime_error{"system time before UNIX epoch"};
29 auto const unix_time_ms = static_cast<std::uint64_t>(unix_time_ms_signed);
30 if (std::countl_zero(unix_time_ms) < 16)
31 throw std::runtime_error{"system time too great"};
27 32
28 auto rand = std::array<unsigned char, 10>{}; 33 auto rand = std::array<unsigned char, 10>{};
29 int s = RAND_bytes(rand.data(), static_cast<int>(rand.size())); 34 int s = RAND_bytes(rand.data(), static_cast<int>(rand.size()));
30 if (s != 1) { 35 if (s != 1)
31 unsigned long e = ERR_get_error(); 36 {
32 throw std::runtime_error{std::format("failed to generate UUID(v7): {} ({}, code {})", ERR_reason_error_string(e), ERR_lib_error_string(e), e)}; 37 unsigned long e = ERR_get_error();
33 } 38 throw std::runtime_error{std::format(
39 "failed to generate UUID(v7): {} ({}, code {})",
40 ERR_reason_error_string(e), ERR_lib_error_string(e), e)};
41 }
34 42
35 auto version = std::uint64_t{0b0111}; 43 auto version = std::uint64_t{0b0111};
36 auto variant = std::uint64_t{0b10}; 44 auto variant = std::uint64_t{0b10};
37 45
38 high_ |= unix_time_ms << 16; 46 high_ |= unix_time_ms << 16;
39 high_ |= version << 12; 47 high_ |= version << 12;
40 high_ |= std::uint64_t{rand[0]} << 4; 48 high_ |= std::uint64_t{rand[0]} << 4;
41 high_ |= std::uint64_t{rand[1]}; 49 high_ |= std::uint64_t{rand[1]};
42 low_ |= variant << 62; 50 low_ |= variant << 62;
43 low_ |= std::uint64_t{rand[2]} << 54; 51 low_ |= std::uint64_t{rand[2]} << 54;
44 low_ |= std::uint64_t{rand[3]} << 48; 52 low_ |= std::uint64_t{rand[3]} << 48;
45 low_ |= std::uint64_t{rand[4]} << 40; 53 low_ |= std::uint64_t{rand[4]} << 40;
46 low_ |= std::uint64_t{rand[5]} << 32; 54 low_ |= std::uint64_t{rand[5]} << 32;
47 low_ |= std::uint64_t{rand[6]} << 24; 55 low_ |= std::uint64_t{rand[6]} << 24;
48 low_ |= std::uint64_t{rand[7]} << 16; 56 low_ |= std::uint64_t{rand[7]} << 16;
49 low_ |= std::uint64_t{rand[8]} << 8; 57 low_ |= std::uint64_t{rand[8]} << 8;
50 low_ |= std::uint64_t{rand[9]}; 58 low_ |= std::uint64_t{rand[9]};
51 } 59 }
52 60
53 auto format(std::array<char, 37>& target) -> void { 61 auto format(std::array<char, 37>& target) -> void
54 auto high_high = (high_ & 0xffff'ffff'0000'0000) >> 32; 62 {
55 auto high_low_high = (high_ & 0x0000'0000'ffff'0000) >> 16; 63 auto high_high = (high_ & 0xffff'ffff'0000'0000) >> 32;
56 auto low_low_high = (high_ & 0x0000'0000'0000'ffff) >> 0; 64 auto high_low_high = (high_ & 0x0000'0000'ffff'0000) >> 16;
57 auto high_low = (low_ & 0xffff'0000'0000'0000) >> 48; 65 auto low_low_high = (high_ & 0x0000'0000'0000'ffff) >> 0;
58 auto low_low = (low_ & 0x0000'ffff'ffff'ffff) >> 0; 66 auto high_low = (low_ & 0xffff'0000'0000'0000) >> 48;
67 auto low_low = (low_ & 0x0000'ffff'ffff'ffff) >> 0;
59 68
60 std::format_to(target.begin(), "{:0>8x}-{:0>4x}-{:0>4x}-{:0>4x}-{:0>12x}", 69 std::format_to(
61 high_high, high_low_high, low_low_high, high_low, low_low); 70 target.begin(), "{:0>8x}-{:0>4x}-{:0>4x}-{:0>4x}-{:0>12x}", high_high,
62 target.back() = '\0'; 71 high_low_high, low_low_high, high_low, low_low);
63 } 72 target.back() = '\0';
64 }; 73 }
74};
65 75
66 export class id { 76export class id
67 std::array<char, 37> chars_; 77{
78 std::array<char, 37> chars_;
68 79
69 public: 80public:
70 id() { 81 id() { uuid7{}.format(chars_); }
71 uuid7{}.format(chars_);
72 }
73 82
74 auto as_string() const -> util::zstring_view { 83 auto as_string() const -> util::zstring_view
75 return util::zstring_view{chars_.data(), chars_.size() - 1}; 84 {
76 } 85 return util::zstring_view{chars_.data(), chars_.size() - 1};
77 }; 86 }
87};
78 88
79} // namespace routemon::trace 89} // namespace routemon::trace