blob: 5f80355d8cc617224f876de6834ffd00f6fd8ea6 [file] [log] [blame]
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +02001#include "report_factory.hpp"
2
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +01003#include "metric.hpp"
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +02004#include "report.hpp"
Wludzik, Jozefe2362792020-10-27 17:23:55 +01005#include "sensor.hpp"
Krzysztof Grobelny80697712021-03-04 09:49:27 +00006#include "utils/clock.hpp"
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +00007#include "utils/conversion.hpp"
Wludzik, Jozef1477fe62021-01-02 11:56:10 +01008#include "utils/dbus_mapper.hpp"
Wludzik, Jozefe2362792020-10-27 17:23:55 +01009#include "utils/transform.hpp"
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020010
11ReportFactory::ReportFactory(
Wludzik, Jozefe2362792020-10-27 17:23:55 +010012 std::shared_ptr<sdbusplus::asio::connection> bus,
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010013 const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
14 SensorCache& sensorCache) :
Wludzik, Jozefe2362792020-10-27 17:23:55 +010015 bus(std::move(bus)),
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010016 objServer(objServer), sensorCache(sensorCache)
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020017{}
18
19std::unique_ptr<interfaces::Report> ReportFactory::make(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010020 const std::string& id, const std::string& name,
21 const ReportingType reportingType,
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010022 const std::vector<ReportAction>& reportActions, Milliseconds period,
23 uint64_t appendLimit, const ReportUpdates reportUpdates,
Szymon Dompke3eb56862021-09-20 15:32:04 +020024 interfaces::ReportManager& reportManager,
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000025 interfaces::JsonStorage& reportStorage,
Krzysztof Grobelny493e62e2022-02-14 10:55:50 +010026 std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
27 Readings readings) const
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020028{
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000029 auto metrics =
30 utils::transform(labeledMetricParams,
31 [this](const LabeledMetricParameters& param)
32 -> std::shared_ptr<interfaces::Metric> {
33 namespace ts = utils::tstring;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000034
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000035 return std::make_shared<Metric>(
36 getSensors(param.at_label<ts::SensorPath>()),
37 param.at_label<ts::OperationType>(),
38 param.at_label<ts::CollectionTimeScope>(),
39 param.at_label<ts::CollectionDuration>(),
40 std::make_unique<Clock>());
41 });
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020042
Krzysztof Grobelny493e62e2022-02-14 10:55:50 +010043 return std::make_unique<Report>(
44 bus->get_io_context(), objServer, id, name, reportingType,
45 reportActions, period, appendLimit, reportUpdates, reportManager,
46 reportStorage, std::move(metrics), *this, enabled,
47 std::make_unique<Clock>(), std::move(readings));
Szymon Dompkefdb06a12022-02-11 11:04:44 +010048}
49
50void ReportFactory::updateMetrics(
51 std::vector<std::shared_ptr<interfaces::Metric>>& metrics, bool enabled,
Szymon Dompke32305f12022-07-05 15:37:21 +020052 const std::vector<LabeledMetricParameters>& labeledMetricParams) const
Szymon Dompkefdb06a12022-02-11 11:04:44 +010053{
Szymon Dompkefdb06a12022-02-11 11:04:44 +010054 std::vector<std::shared_ptr<interfaces::Metric>> oldMetrics = metrics;
55 std::vector<std::shared_ptr<interfaces::Metric>> newMetrics;
56
57 for (const auto& labeledMetricParam : labeledMetricParams)
58 {
59 auto existing = std::find_if(oldMetrics.begin(), oldMetrics.end(),
60 [labeledMetricParam](auto metric) {
Patrick Williams3a1c2972023-05-10 07:51:04 -050061 return labeledMetricParam == metric->dumpConfiguration();
62 });
Szymon Dompkefdb06a12022-02-11 11:04:44 +010063
64 if (existing != oldMetrics.end())
65 {
66 newMetrics.emplace_back(*existing);
67 oldMetrics.erase(existing);
68 continue;
69 }
70
71 namespace ts = utils::tstring;
72 newMetrics.emplace_back(std::make_shared<Metric>(
73 getSensors(labeledMetricParam.at_label<ts::SensorPath>()),
74 labeledMetricParam.at_label<ts::OperationType>(),
Szymon Dompkefdb06a12022-02-11 11:04:44 +010075 labeledMetricParam.at_label<ts::CollectionTimeScope>(),
76 labeledMetricParam.at_label<ts::CollectionDuration>(),
77 std::make_unique<Clock>()));
78
79 if (enabled)
80 {
81 newMetrics.back()->initialize();
82 }
83 }
84
85 if (enabled)
86 {
87 for (auto& metric : oldMetrics)
88 {
89 metric->deinitialize();
90 }
91 }
92
93 metrics = std::move(newMetrics);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020094}
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010095
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000096Sensors ReportFactory::getSensors(
Szymon Dompke94f71c52021-12-10 07:16:33 +010097 const std::vector<LabeledSensorInfo>& sensorPaths) const
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010098{
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000099 using namespace utils::tstring;
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100100
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100101 return utils::transform(
102 sensorPaths,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100103 [this](const LabeledSensorInfo& sensorPath)
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100104 -> std::shared_ptr<interfaces::Sensor> {
105 return sensorCache.makeSensor<Sensor>(
106 sensorPath.at_label<Service>(), sensorPath.at_label<Path>(),
107 sensorPath.at_label<Metadata>(), bus->get_io_context(), bus);
108 });
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100109}
110
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000111std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
112 boost::asio::yield_context& yield,
113 const ReadingParameters& metricParams) const
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100114{
Szymon Dompkefdb06a12022-02-11 11:04:44 +0100115 if (metricParams.empty())
116 {
117 return {};
118 }
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200119
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100120 auto tree = utils::getSubTreeSensors(yield, bus);
Szymon Dompkefdb06a12022-02-11 11:04:44 +0100121 return getMetricParamsFromSensorTree(metricParams, tree);
122}
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000123
Szymon Dompkefdb06a12022-02-11 11:04:44 +0100124std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
125 const ReadingParameters& metricParams) const
126{
127 if (metricParams.empty())
128 {
129 return {};
130 }
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200131
Szymon Dompkefdb06a12022-02-11 11:04:44 +0100132 auto tree = utils::getSubTreeSensors(bus);
133 return getMetricParamsFromSensorTree(metricParams, tree);
134}
135
136std::vector<LabeledMetricParameters>
137 ReportFactory::getMetricParamsFromSensorTree(
138 const ReadingParameters& metricParams,
139 const std::vector<utils::SensorTree>& tree) const
140{
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200141 try
142 {
143 return utils::transform(metricParams, [&tree](const auto& item) {
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +0000144 auto [sensorPaths, operationType, collectionTimeScope,
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200145 collectionDuration] = item;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000146
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200147 std::vector<LabeledSensorInfo> sensorParameters;
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000148
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200149 for (const auto& [sensorPath, metadata] : sensorPaths)
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000150 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200151 auto it = std::find_if(tree.begin(), tree.end(),
152 [path = sensorPath](const auto& v) {
Patrick Williams3a1c2972023-05-10 07:51:04 -0500153 return v.first == path;
154 });
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200155
156 if (it != tree.end() && it->second.size() == 1)
157 {
158 const auto& [service, ifaces] = it->second.front();
159 sensorParameters.emplace_back(service, sensorPath,
160 metadata);
161 }
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000162 }
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200163
164 if (sensorParameters.size() != sensorPaths.size())
165 {
166 throw errors::InvalidArgument("ReadingParameters",
167 "Service not found.");
168 }
169
170 if (operationType.empty())
171 {
172 operationType = utils::enumToString(OperationType::avg);
173 }
174 else if (operationType == "SINGLE")
175 {
176 operationType = utils::enumToString(OperationType::avg);
177 collectionTimeScope =
178 utils::enumToString(CollectionTimeScope::point);
179 }
180
181 if (collectionTimeScope.empty())
182 {
183 collectionTimeScope =
184 utils::enumToString(CollectionTimeScope::point);
185 }
186
187 return LabeledMetricParameters(
188 std::move(sensorParameters),
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +0000189 utils::toOperationType(operationType),
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200190 utils::toCollectionTimeScope(collectionTimeScope),
191 CollectionDuration(Milliseconds(collectionDuration)));
192 });
193 }
194 catch (const errors::InvalidArgument& e)
195 {
196 if (e.propertyName == "ReadingParameters")
197 {
198 throw;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000199 }
200
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200201 using namespace std::literals::string_literals;
202 throw errors::InvalidArgument("ReadingParameters."s + e.propertyName);
203 }
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100204}