summaryrefslogtreecommitdiffhomepage
path: root/statistics.cpp
blob: 19d02581c851617b08a8feec4d8b0ccd53cd9a75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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();
}