blob: c7982476fe23d7c32cb7268365ab89ad60dc47f1 [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) :
Patrick Williamsf535cad2024-08-16 15:21:20 -040015 bus(std::move(bus)), objServer(objServer), sensorCache(sensorCache)
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020016{}
17
18std::unique_ptr<interfaces::Report> ReportFactory::make(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010019 const std::string& id, const std::string& name,
20 const ReportingType reportingType,
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010021 const std::vector<ReportAction>& reportActions, Milliseconds period,
22 uint64_t appendLimit, const ReportUpdates reportUpdates,
Szymon Dompke3eb56862021-09-20 15:32:04 +020023 interfaces::ReportManager& reportManager,
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000024 interfaces::JsonStorage& reportStorage,
Krzysztof Grobelny493e62e2022-02-14 10:55:50 +010025 std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
26 Readings readings) const
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020027{
Patrick Williamsc7935fa2023-10-20 11:19:30 -050028 auto metrics = utils::transform(labeledMetricParams,
29 [this](const LabeledMetricParameters& param)
30 -> std::shared_ptr<interfaces::Metric> {
31 namespace ts = utils::tstring;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000032
Patrick Williamsc7935fa2023-10-20 11:19:30 -050033 return std::make_shared<Metric>(
34 getSensors(param.at_label<ts::SensorPath>()),
35 param.at_label<ts::OperationType>(),
36 param.at_label<ts::CollectionTimeScope>(),
37 param.at_label<ts::CollectionDuration>(),
38 std::make_unique<Clock>());
39 });
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020040
Krzysztof Grobelny493e62e2022-02-14 10:55:50 +010041 return std::make_unique<Report>(
42 bus->get_io_context(), objServer, id, name, reportingType,
43 reportActions, period, appendLimit, reportUpdates, reportManager,
44 reportStorage, std::move(metrics), *this, enabled,
45 std::make_unique<Clock>(), std::move(readings));
Szymon Dompkefdb06a12022-02-11 11:04:44 +010046}
47
48void ReportFactory::updateMetrics(
49 std::vector<std::shared_ptr<interfaces::Metric>>& metrics, bool enabled,
Szymon Dompke32305f12022-07-05 15:37:21 +020050 const std::vector<LabeledMetricParameters>& labeledMetricParams) const
Szymon Dompkefdb06a12022-02-11 11:04:44 +010051{
Szymon Dompkefdb06a12022-02-11 11:04:44 +010052 std::vector<std::shared_ptr<interfaces::Metric>> oldMetrics = metrics;
53 std::vector<std::shared_ptr<interfaces::Metric>> newMetrics;
54
55 for (const auto& labeledMetricParam : labeledMetricParams)
56 {
57 auto existing = std::find_if(oldMetrics.begin(), oldMetrics.end(),
58 [labeledMetricParam](auto metric) {
Patrick Williams3a1c2972023-05-10 07:51:04 -050059 return labeledMetricParam == metric->dumpConfiguration();
60 });
Szymon Dompkefdb06a12022-02-11 11:04:44 +010061
62 if (existing != oldMetrics.end())
63 {
64 newMetrics.emplace_back(*existing);
65 oldMetrics.erase(existing);
66 continue;
67 }
68
69 namespace ts = utils::tstring;
70 newMetrics.emplace_back(std::make_shared<Metric>(
71 getSensors(labeledMetricParam.at_label<ts::SensorPath>()),
72 labeledMetricParam.at_label<ts::OperationType>(),
Szymon Dompkefdb06a12022-02-11 11:04:44 +010073 labeledMetricParam.at_label<ts::CollectionTimeScope>(),
74 labeledMetricParam.at_label<ts::CollectionDuration>(),
75 std::make_unique<Clock>()));
76
77 if (enabled)
78 {
79 newMetrics.back()->initialize();
80 }
81 }
82
83 if (enabled)
84 {
85 for (auto& metric : oldMetrics)
86 {
87 metric->deinitialize();
88 }
89 }
90
91 metrics = std::move(newMetrics);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020092}
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010093
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000094Sensors ReportFactory::getSensors(
Szymon Dompke94f71c52021-12-10 07:16:33 +010095 const std::vector<LabeledSensorInfo>& sensorPaths) const
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010096{
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000097 using namespace utils::tstring;
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010098
Patrick Williamsc7935fa2023-10-20 11:19:30 -050099 return utils::transform(sensorPaths,
100 [this](const LabeledSensorInfo& sensorPath)
101 -> std::shared_ptr<interfaces::Sensor> {
102 return sensorCache.makeSensor<Sensor>(
103 sensorPath.at_label<Service>(), sensorPath.at_label<Path>(),
104 sensorPath.at_label<Metadata>(), bus->get_io_context(), bus);
105 });
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100106}
107
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000108std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
109 boost::asio::yield_context& yield,
110 const ReadingParameters& metricParams) const
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100111{
Szymon Dompkefdb06a12022-02-11 11:04:44 +0100112 if (metricParams.empty())
113 {
114 return {};
115 }
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200116
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100117 auto tree = utils::getSubTreeSensors(yield, bus);
Szymon Dompkefdb06a12022-02-11 11:04:44 +0100118 return getMetricParamsFromSensorTree(metricParams, tree);
119}
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000120
Szymon Dompkefdb06a12022-02-11 11:04:44 +0100121std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
122 const ReadingParameters& metricParams) const
123{
124 if (metricParams.empty())
125 {
126 return {};
127 }
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200128
Szymon Dompkefdb06a12022-02-11 11:04:44 +0100129 auto tree = utils::getSubTreeSensors(bus);
130 return getMetricParamsFromSensorTree(metricParams, tree);
131}
132
133std::vector<LabeledMetricParameters>
134 ReportFactory::getMetricParamsFromSensorTree(
135 const ReadingParameters& metricParams,
136 const std::vector<utils::SensorTree>& tree) const
137{
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200138 try
139 {
140 return utils::transform(metricParams, [&tree](const auto& item) {
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +0000141 auto [sensorPaths, operationType, collectionTimeScope,
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200142 collectionDuration] = item;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000143
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200144 std::vector<LabeledSensorInfo> sensorParameters;
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000145
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200146 for (const auto& [sensorPath, metadata] : sensorPaths)
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000147 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200148 auto it = std::find_if(tree.begin(), tree.end(),
149 [path = sensorPath](const auto& v) {
Patrick Williams3a1c2972023-05-10 07:51:04 -0500150 return v.first == path;
151 });
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200152
153 if (it != tree.end() && it->second.size() == 1)
154 {
155 const auto& [service, ifaces] = it->second.front();
156 sensorParameters.emplace_back(service, sensorPath,
157 metadata);
158 }
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000159 }
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200160
161 if (sensorParameters.size() != sensorPaths.size())
162 {
163 throw errors::InvalidArgument("ReadingParameters",
164 "Service not found.");
165 }
166
167 if (operationType.empty())
168 {
169 operationType = utils::enumToString(OperationType::avg);
170 }
171 else if (operationType == "SINGLE")
172 {
173 operationType = utils::enumToString(OperationType::avg);
174 collectionTimeScope =
175 utils::enumToString(CollectionTimeScope::point);
176 }
177
178 if (collectionTimeScope.empty())
179 {
180 collectionTimeScope =
181 utils::enumToString(CollectionTimeScope::point);
182 }
183
184 return LabeledMetricParameters(
185 std::move(sensorParameters),
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +0000186 utils::toOperationType(operationType),
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200187 utils::toCollectionTimeScope(collectionTimeScope),
188 CollectionDuration(Milliseconds(collectionDuration)));
189 });
190 }
191 catch (const errors::InvalidArgument& e)
192 {
193 if (e.propertyName == "ReadingParameters")
194 {
195 throw;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000196 }
197
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200198 using namespace std::literals::string_literals;
199 throw errors::InvalidArgument("ReadingParameters."s + e.propertyName);
200 }
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100201}