code wiki / _hdl_build / nx_metrics_ring.nx

nx_metrics_ring.nx source

↩ module page · 130 lines · 5295 B

1// nx_metrics_ring.nx -- SOVEREIGN metrics time-series store (the TSDB the maturity census named as the 2// supervisor domain's #1 observability gap: /status is point-in-time, there was NO history). A fixed-size 3// binary RING (no SQL, no float, no TSV -- append-only, WRAPS at capacity so disk is BOUNDED by construction, 4// respecting the disk-budget law). Each sample = 32 bytes: ts_sec | name_hash(FNV-1a) | verdict | fails. 5// Library half (no main): the sampler daemon appends; the CLI + nx_heal query. license_tier: ORIGINAL 6import "nx_syscalls.nx" 7const MR_MAGIC_2166136261: i64 = 2166136261 8const MR_MAGIC_16777619: i64 = 16777619 9const MR_MAGIC_4294967295: i64 = 4294967295 10 11const MR_MAGIC: i64 = 5928237 // ring header sentinel 12const MR_HDR: i64 = 64 // header bytes 13const MR_REC: i64 = 32 // record bytes: ts(8) namehash(8) verdict(8) fails(8) 14const MR_CAP: i64 = 262144 // ~8.4MB file, ~29h of 37-daemon 15s samples (bounded) 15const MR_V_SERVING: i64 = 1 16const MR_V_REFUSED: i64 = 2 17const MR_V_HUNG: i64 = 3 18const MR_V_BADRESP: i64 = 4 19 20func mr_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 21// FNV-1a 32-bit (masked, positive) -- daemon identity without variable-length strings in the record. 22func mr_hash(s: *u8) -> i64 { 23 var h: i64 = MR_MAGIC_2166136261 24 var i: i64 = 0 25 while s[i] != (0 as u8) { 26 h = h ^ (s[i] as i64) 27 h = (h * MR_MAGIC_16777619) & MR_MAGIC_4294967295 28 i = i + 1 29 } 30 return h 31} 32// read n bytes at offset off into buf; returns bytes read (or -1) 33func mr_pread(fd: i64, off: i64, buf: *u8, n: i64) -> i64 { 34 if sys_lseek(fd, off, 0) < 0 { return 0 - 1 } 35 var t: i64 = 0 36 while t < n { let r: i64 = sys_read(fd, (buf as i64 + t) as *u8, n - t); if r <= 0 { return t } t = t + r } 37 return t 38} 39func mr_pwrite(fd: i64, off: i64, buf: *u8, n: i64) -> i64 { 40 if sys_lseek(fd, off, 0) < 0 { return 0 - 1 } 41 var t: i64 = 0 42 while t < n { let w: i64 = sys_write(fd, (buf as i64 + t) as *u8, n - t); if w <= 0 { return 0 - 1 } t = t + w } 43 return 0 44} 45func mr_geti(buf: *u8, o: i64) -> i64 { 46 var v: i64 = 0 47 var i: i64 = 0 48 while i < 8 { v = v | ((buf[o + i] as i64) << (i * 8)); i = i + 1 } 49 return v 50} 51func mr_puti(buf: *u8, o: i64, v: i64) -> i64 { 52 var i: i64 = 0 53 while i < 8 { buf[o + i] = ((v >> (i * 8)) & 255) as u8; i = i + 1 } 54 return 0 55} 56 57// append one sample. Self-contained + FAIL-SAFE (any error -> return negative, never crashes a caller). 58// open O_RDWR|CREAT, init header if new/foreign, write record at write_index, advance (wrap), rewrite header. 59func mr_append(path: *u8, ts: i64, namehash: i64, verdict: i64, fails: i64) -> i64 { 60 let fd: i64 = sys_openat_rdwr(path, 420) 61 if fd < 0 { return 0 - 1 } 62 let hdr: *u8 = sys_mmap(MR_HDR) 63 let got: i64 = mr_pread(fd, 0, hdr, MR_HDR) 64 var widx: i64 = 0 65 var wrapped: i64 = 0 66 if got == MR_HDR { if mr_geti(hdr, 0) == MR_MAGIC { 67 widx = mr_geti(hdr, 24) 68 wrapped = mr_geti(hdr, 32) 69 } } 70 // (re)write a valid header baseline 71 var hi: i64 = 0; while hi < MR_HDR { hdr[hi] = 0 as u8; hi = hi + 1 } 72 mr_puti(hdr, 0, MR_MAGIC) 73 mr_puti(hdr, 8, MR_REC) 74 mr_puti(hdr, 16, MR_CAP) 75 // record 76 let rec: *u8 = sys_mmap(MR_REC) 77 mr_puti(rec, 0, ts) 78 mr_puti(rec, 8, namehash) 79 mr_puti(rec, 16, verdict) 80 mr_puti(rec, 24, fails) 81 let recoff: i64 = MR_HDR + widx * MR_REC 82 if mr_pwrite(fd, recoff, rec, MR_REC) != 0 { sys_close(fd); sys_munmap(hdr, MR_HDR); sys_munmap(rec, MR_REC); return 0 - 2 } 83 var nidx: i64 = widx + 1 84 if nidx >= MR_CAP { nidx = 0; wrapped = 1 } 85 mr_puti(hdr, 24, nidx) 86 mr_puti(hdr, 32, wrapped) 87 mr_pwrite(fd, 0, hdr, MR_HDR) 88 sys_close(fd) 89 // free per-call scratch -- mr_append runs in the sampler's hot loop (the bounded-VSZ discipline) 90 sys_munmap(hdr, MR_HDR) 91 sys_munmap(rec, MR_REC) 92 return 0 93} 94 95// count of valid records currently stored 96func mr_count(fd: i64, hdr: *u8) -> i64 { 97 if mr_pread(fd, 0, hdr, MR_HDR) != MR_HDR { return 0 } 98 if mr_geti(hdr, 0) != MR_MAGIC { return 0 } 99 if mr_geti(hdr, 32) == 1 { return MR_CAP } 100 return mr_geti(hdr, 24) 101} 102 103// uptime permille for namehash over [now-window, now]. -1 if no samples. verdict==SERVING = "up". 104func mr_uptime(path: *u8, namehash: i64, window_sec: i64, now: i64) -> i64 { 105 let fd: i64 = sys_openat_rd(path) 106 if fd < 0 { return 0 - 1 } 107 let hdr: *u8 = sys_mmap(MR_HDR) 108 let cnt: i64 = mr_count(fd, hdr) 109 if cnt <= 0 { sys_close(fd); return 0 - 1 } 110 let rec: *u8 = sys_mmap(MR_REC) 111 var total: i64 = 0 112 var up: i64 = 0 113 let lo: i64 = now - window_sec 114 var i: i64 = 0 115 while i < cnt { 116 if mr_pread(fd, MR_HDR + i * MR_REC, rec, MR_REC) == MR_REC { 117 if mr_geti(rec, 8) == namehash { 118 let ts: i64 = mr_geti(rec, 0) 119 if ts >= lo { if ts <= now { 120 total = total + 1 121 if mr_geti(rec, 16) == MR_V_SERVING { up = up + 1 } 122 } } 123 } 124 } 125 i = i + 1 126 } 127 sys_close(fd) 128 if total <= 0 { return 0 - 1 } 129 return up * 1000 / total 130}