feat: auto-flush stats timer, .env.json defaults, expose round-trip+timer tests
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
// Minimal libpq declarations (no dev headers on build hosts); link -lpq.
|
||||
extern "C" {
|
||||
@@ -283,6 +284,31 @@ std::unique_ptr<StatsStore> MakeStatsStore(const std::string& database_url) {
|
||||
return std::make_unique<SqliteStore>(path);
|
||||
}
|
||||
|
||||
static int FlushIntervalSecs() {
|
||||
std::string v = EnvJsonValue("STATS_FLUSH_SECS");
|
||||
if (v.empty()) v = EnvOr("STATS_FLUSH_SECS", "5");
|
||||
try { int n = std::stoi(v); return n > 0 ? n : 5; } catch (...) { return 5; }
|
||||
}
|
||||
|
||||
void StatsCollector::StartAutoFlush(std::chrono::seconds interval) {
|
||||
StopAutoFlush();
|
||||
if (interval.count() <= 0) interval = std::chrono::seconds(FlushIntervalSecs());
|
||||
flush_run_.store(true);
|
||||
flush_thread_ = std::thread([this, interval] {
|
||||
while (flush_run_.load()) {
|
||||
std::this_thread::sleep_for(interval);
|
||||
if (!flush_run_.load()) break;
|
||||
std::string err;
|
||||
Flush(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void StatsCollector::StopAutoFlush() {
|
||||
flush_run_.store(false);
|
||||
if (flush_thread_.joinable()) flush_thread_.join();
|
||||
}
|
||||
|
||||
StatsCollector& StatsCollector::Global() {
|
||||
static StatsCollector g;
|
||||
return g;
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
// atomic in-memory accumulator + a pluggable Store backend; flush is
|
||||
// explicit (timer-driven by caller) inside one transaction.
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <thread>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -49,6 +51,12 @@ class StatsCollector {
|
||||
}
|
||||
bool enabled() const { return enabled_.load(std::memory_order_relaxed); }
|
||||
void set_enabled(bool v) { enabled_.store(v, std::memory_order_relaxed); }
|
||||
~StatsCollector() { StopAutoFlush(); }
|
||||
// Time-based persisted flush: background thread calls Flush() every
|
||||
// interval (default 5s; STATS_FLUSH_SECS in .env.json/env overrides).
|
||||
// Idempotent; safe to call twice.
|
||||
void StartAutoFlush(std::chrono::seconds interval = std::chrono::seconds(5));
|
||||
void StopAutoFlush();
|
||||
|
||||
void Note(const std::string& method, std::uint64_t bytes_in,
|
||||
std::uint64_t bytes_out, std::uint64_t latency_us);
|
||||
@@ -61,6 +69,8 @@ class StatsCollector {
|
||||
std::mutex mu_;
|
||||
std::unique_ptr<StatsStore> store_;
|
||||
std::map<std::string, MethodStat> pending_;
|
||||
std::thread flush_thread_;
|
||||
std::atomic<bool> flush_run_{false};
|
||||
};
|
||||
|
||||
} // namespace molo::realtime::expose
|
||||
|
||||
Reference in New Issue
Block a user