blob: 951225280276fcb3dfe59ab9853d159a3f8e5e49 [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) :
38 function(std::move(function)),
39 duration(duration)
40 {
41 if (duration.t.count() == 0)
42 {
43 throw sdbusplus::exception::SdBusError(
44 static_cast<int>(std::errc::invalid_argument),
45 "Invalid CollectionDuration");
46 }
47 }
48
49 std::optional<double> update(Milliseconds timestamp) override
50 {
51 if (readings.empty())
52 {
53 return std::nullopt;
54 }
55
56 cleanup(timestamp);
57
58 return function->calculate(readings, timestamp);
59 }
60
61 double update(Milliseconds timestamp, double reading) override
62 {
63 readings.emplace_back(timestamp, reading);
64
65 cleanup(timestamp);
66
67 return function->calculate(readings, timestamp);
68 }
69
70 private:
71 void cleanup(Milliseconds timestamp)
72 {
73 auto it = readings.begin();
74 for (auto kt = std::next(readings.rbegin()); kt != readings.rend();
75 ++kt)
76 {
77 const auto& [nextItemTimestamp, nextItemReading] = *std::prev(kt);
78 if (timestamp >= nextItemTimestamp &&
79 timestamp - nextItemTimestamp > duration.t)
80 {
81 it = kt.base();
82 break;
83 }
84 }
85 readings.erase(readings.begin(), it);
86
87 if (timestamp > duration.t)
88 {
89 readings.front().first =
90 std::max(readings.front().first, timestamp - duration.t);
91 }
92 }
93
94 std::shared_ptr<CollectionFunction> function;
95 std::vector<ReadingItem> readings;
96 CollectionDuration duration;
97};
98
99class DataStartup : public CollectionData
100{
101 public:
102 explicit DataStartup(std::shared_ptr<CollectionFunction> function) :
103 function(std::move(function))
104 {}
105
106 std::optional<double> update(Milliseconds timestamp) override
107 {
108 if (readings.empty())
109 {
110 return std::nullopt;
111 }
112
113 return function->calculateForStartupInterval(readings, timestamp);
114 }
115
116 double update(Milliseconds timestamp, double reading) override
117 {
118 readings.emplace_back(timestamp, reading);
119 return function->calculateForStartupInterval(readings, timestamp);
120 }
121
122 private:
123 std::shared_ptr<CollectionFunction> function;
124 std::vector<ReadingItem> readings;
125};
126
127std::vector<std::unique_ptr<CollectionData>>
128 makeCollectionData(size_t size, OperationType op,
129 CollectionTimeScope timeScope,
130 CollectionDuration duration)
131{
132 using namespace std::string_literals;
133
134 std::vector<std::unique_ptr<CollectionData>> result;
135
136 result.reserve(size);
137
138 switch (timeScope)
139 {
140 case CollectionTimeScope::interval:
141 std::generate_n(std::back_inserter(result), size,
142 [cf = makeCollectionFunction(op), duration] {
143 return std::make_unique<DataInterval>(cf,
144 duration);
145 });
146 break;
147 case CollectionTimeScope::point:
148 std::generate_n(std::back_inserter(result), size,
149 [] { return std::make_unique<DataPoint>(); });
150 break;
151 case CollectionTimeScope::startup:
152 std::generate_n(std::back_inserter(result), size,
153 [cf = makeCollectionFunction(op)] {
154 return std::make_unique<DataStartup>(cf);
155 });
156 break;
157 }
158
159 return result;
160}
161
162} // namespace metrics