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:
@@ -21,6 +21,8 @@ struct MethodStat {
|
||||
std::uint64_t bytes_in = 0;
|
||||
std::uint64_t bytes_out = 0;
|
||||
std::uint64_t latency_us_sum = 0;
|
||||
double kb_s_in = 0.0; // windowed throughput at last flush
|
||||
double kb_s_out = 0.0;
|
||||
};
|
||||
|
||||
struct StatsSnapshot {
|
||||
@@ -40,8 +42,13 @@ class StatsStore {
|
||||
|
||||
std::unique_ptr<StatsStore> MakeStatsStore(const std::string& database_url);
|
||||
|
||||
// Zero-cost when idle: Note() is lock-free atomics only. Flush() swaps
|
||||
// the accumulator under a short mutex and writes one transaction.
|
||||
// Zero-cost fast path: Note() is lock-free atomics after first-seen
|
||||
// method registration (thread-local index cache; mutex only on new-method
|
||||
// insert and on Flush swap). Disabled Note() is a single atomic load.
|
||||
// Windowed kb/s up/down computed per flush interval from byte deltas.
|
||||
struct StatCell {
|
||||
std::atomic<std::uint64_t> count{0}, bytes_in{0}, bytes_out{0}, latency_us_sum{0};
|
||||
};
|
||||
class StatsCollector {
|
||||
public:
|
||||
static StatsCollector& Global();
|
||||
@@ -64,11 +71,24 @@ class StatsCollector {
|
||||
bool Flush(std::string& err);
|
||||
bool Query(std::string& out, bool as_json, std::string& err);
|
||||
|
||||
// Windowed throughput from last flush (updated under mu_ on Flush).
|
||||
double RateIn() const { return kb_s_in_; }
|
||||
double RateOut() const { return kb_s_out_; }
|
||||
|
||||
private:
|
||||
friend class StatsCollectorTestHook;
|
||||
size_t CellFor(const std::string& method); // mutex only on new method
|
||||
std::atomic<bool> enabled_{true};
|
||||
std::mutex mu_;
|
||||
std::unique_ptr<StatsStore> store_;
|
||||
std::map<std::string, MethodStat> pending_;
|
||||
std::map<std::string, MethodStat> pending_; // drained via cells on Flush
|
||||
std::map<std::string, size_t> method_idx_;
|
||||
std::vector<std::unique_ptr<StatCell>> cells_;
|
||||
std::vector<std::string> cell_names_;
|
||||
std::mutex idx_mu_;
|
||||
std::uint64_t flush_bytes_in_ = 0, flush_bytes_out_ = 0;
|
||||
std::chrono::steady_clock::time_point last_flush_tp_ = std::chrono::steady_clock::now();
|
||||
double kb_s_in_ = 0.0, kb_s_out_ = 0.0;
|
||||
std::thread flush_thread_;
|
||||
std::atomic<bool> flush_run_{false};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user