summaryrefslogtreecommitdiffhomepage
path: root/statistics.cpp
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-04-25 18:36:54 +0200
committerRoland Reichwein <mail@reichwein.it>2020-04-25 18:36:54 +0200
commit683d2cb48c4f3620fc3be68ba97b2d3bb5a40e30 (patch)
tree8c0ae6438f6ec706a170eb41f683d6c91dc4a800 /statistics.cpp
parentb2c34d03399978a3d0838ee7ed92c760e7908721 (diff)
Added statistics
Diffstat (limited to 'statistics.cpp')
-rw-r--r--statistics.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/statistics.cpp b/statistics.cpp
new file mode 100644
index 0000000..19d0258
--- /dev/null
+++ b/statistics.cpp
@@ -0,0 +1,87 @@
+#include "statistics.h"
+
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+
+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<std::mutex> 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<std::mutex> lock(mMutex);
+
+ if (mBins.empty() || mBins.back().expired()) {
+ mBins.emplace_back(Bin{static_cast<uint64_t>((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();
+}
+