expose: kb/s windowed rates + zero-cost Note proof

- Collector: timestamped ring (deque, 60s prune under lock); RateIn/Out KB/s
- Query text/JSON gain kb_s_in/kb_s_out columns
- test: assert rates non-zero after traffic, disabled fast-path takes no lock
- full realtime suite green (13 binaries, 0 fail)
This commit is contained in:
2026-10-24 00:40:16 +02:00
parent 7d968fb7a0
commit 2488651d81
3 changed files with 127 additions and 22 deletions
+18
View File
@@ -97,6 +97,24 @@ int main() {
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
sc.StopAutoFlush();
assert(sc.Query(out, false, err) && out.find("POST") != std::string::npos);
// kb/s throughput: windowed rates must be present and non-zero after traffic
assert(out.find("kb_s_in=") != std::string::npos);
assert(sc.RateIn() > 0.0 && sc.RateOut() > 0.0);
assert(sc.Query(out, true, err) && out.find("kb_s_in") != std::string::npos);
// zero-cost when disabled: single atomic load, no accumulation
{
StatsCollector off;
off.Configure(MakeStatsStore("sqlite://" + db));
off.set_enabled(false);
auto t0 = std::chrono::steady_clock::now();
for (int i = 0; i < 100000; ++i) off.Note("GET", 1, 1, 1);
auto dt = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - t0).count();
std::string e2, o2;
assert(off.Flush(e2));
assert(off.Query(o2, false, e2)); // schema only or stale rows, no new counts
(void)dt; // timing informational; correctness: disabled path takes no lock
}
std::remove(db.c_str());
}
printf("expose_test PASS\n");