blob: 915f5706162669e080c795f7853f1a331a430d9a [file] [log] [blame]
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +01001#include "metrics/collection_data.hpp"
2
3#include "metrics/collection_function.hpp"
4
5namespace metrics
6{
7
8bool CollectionData::updateLastValue(double value)
9{
10 const bool changed = lastValue != value;
11 lastValue = value;
12 return changed;
13}
14
15class DataPoint : public CollectionData
16{
17 public:
18 std::optional<double> update(Milliseconds) override
19 {
20 return lastReading;
21 }
22
23 double update(Milliseconds, double reading) override
24 {
25 lastReading = reading;
26 return reading;
27 }
28
29 private:
30 std::optional<double> lastReading;
31};
32
33class DataInterval : public CollectionData
34{
35 public:
36 DataInterval(std::shared_ptr<CollectionFunction> function,
37 CollectionDuration duration) :
Patrick Williamsf535cad2024-08-16 15:21:20 -040038 function(std::move(function)), duration(duration)
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010039 {
40 if (duration.t.count() == 0)
41 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +020042 throw errors::InvalidArgument(
43 "ReadingParameters.CollectionDuration");
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010044 }
45 }
46
47 std::optional<double> update(Milliseconds timestamp) override
48 {
49 if (readings.empty())
50 {
51 return std::nullopt;
52 }
53
54 cleanup(timestamp);
55
56 return function->calculate(readings, timestamp);
57 }
58
59 double update(Milliseconds timestamp, double reading) override
60 {
61 readings.emplace_back(timestamp, reading);
62
63 cleanup(timestamp);
64
65 return function->calculate(readings, timestamp);
66 }
67
68 private:
69 void cleanup(Milliseconds timestamp)
70 {
71 auto it = readings.begin();
72 for (auto kt = std::next(readings.rbegin()); kt != readings.rend();
73 ++kt)
74 {
75 const auto& [nextItemTimestamp, nextItemReading] = *std::prev(kt);
76 if (timestamp >= nextItemTimestamp &&
77 timestamp - nextItemTimestamp > duration.t)
78 {
79 it = kt.base();
80 break;
81 }
82 }
83 readings.erase(readings.begin(), it);
84
85 if (timestamp > duration.t)
86 {
Patrick Williams3a1c2972023-05-10 07:51:04 -050087 readings.front().first = std::max(readings.front().first,
88 timestamp - duration.t);
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010089 }
90 }
91
92 std::shared_ptr<CollectionFunction> function;
93 std::vector<ReadingItem> readings;
94 CollectionDuration duration;
95};
96
97class DataStartup : public CollectionData
98{
99 public:
100 explicit DataStartup(std::shared_ptr<CollectionFunction> function) :
101 function(std::move(function))
102 {}
103
104 std::optional<double> update(Milliseconds timestamp) override
105 {
106 if (readings.empty())
107 {
108 return std::nullopt;
109 }
110
111 return function->calculateForStartupInterval(readings, timestamp);
112 }
113
114 double update(Milliseconds timestamp, double reading) override
115 {
116 readings.emplace_back(timestamp, reading);
117 return function->calculateForStartupInterval(readings, timestamp);
118 }
119
120 private:
121 std::shared_ptr<CollectionFunction> function;
122 std::vector<ReadingItem> readings;
123};
124
125std::vector<std::unique_ptr<CollectionData>>
126 makeCollectionData(size_t size, OperationType op,
127 CollectionTimeScope timeScope,
128 CollectionDuration duration)
129{
130 using namespace std::string_literals;
131
132 std::vector<std::unique_ptr<CollectionData>> result;
133
134 result.reserve(size);
135
136 switch (timeScope)
137 {
138 case CollectionTimeScope::interval:
139 std::generate_n(std::back_inserter(result), size,
140 [cf = makeCollectionFunction(op), duration] {
Patrick Williams3a1c2972023-05-10 07:51:04 -0500141 return std::make_unique<DataInterval>(cf, duration);
142 });
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100143 break;
144 case CollectionTimeScope::point:
145 std::generate_n(std::back_inserter(result), size,
146 [] { return std::make_unique<DataPoint>(); });
147 break;
148 case CollectionTimeScope::startup:
149 std::generate_n(std::back_inserter(result), size,
150 [cf = makeCollectionFunction(op)] {
Patrick Williams3a1c2972023-05-10 07:51:04 -0500151 return std::make_unique<DataStartup>(cf);
152 });
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100153 break;
154 }
155
156 return result;
157}
158
159} // namespace metrics