#include "statistics.h" #include #include #include namespace fs = std::filesystem; namespace { const fs::path statsfilepath{ "/var/lib/webserver/stats.db" }; } // anonymous namespace Statistics::Statistics() { std::cout << "Loading statistics..." << std::endl; std::ifstream file{statsfilepath, std::ios::in | std::ios::binary}; if (file.is_open()) { Serialization::IArchive archive{file}; archive >> mBins; } else { std::cerr << "Warning: Couldn't read statistics" << std::endl; } } Statistics::~Statistics() { std::cout << "Saving statistics..." << std::endl; std::lock_guard lock(mMutex); std::ofstream file{statsfilepath, std::ios::out | std::ios::binary | std::ios::trunc}; if (file.is_open()) { Serialization::OArchive archive{file}; archive << mBins; } else { std::cerr << "Warning: Couldn't write statistics" << std::endl; } } bool Statistics::Bin::expired() const { auto now {time(nullptr)}; if (now < start_time) std::runtime_error("Statistics time is in the future"); return start_time + binsize < now; } void Statistics::limit() { while (mBins.size() * sizeof(Bin) > maxSize) mBins.pop_front(); // discard oldest element } void Statistics::count(size_t bytes_in, size_t bytes_out, bool error, bool ipv6, bool https) { std::lock_guard lock(mMutex); if (mBins.empty() || mBins.back().expired()) { mBins.emplace_back(Bin{static_cast((time(nullptr) / binsize) * binsize), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); } Bin& bin{mBins.back()}; bin.requests++; if (error) bin.errors++; bin.bytes_in += bytes_in; bin.bytes_out += bytes_out; if (ipv6) { bin.requests_ipv6++; if (error) bin.errors_ipv6++; bin.bytes_in_ipv6 += bytes_in; bin.bytes_out_ipv6 += bytes_out; } if (https) { bin.requests_https++; if (error) bin.errors_https++; bin.bytes_in_https += bytes_in; bin.bytes_out_https += bytes_out; } limit(); }