1 #include "report_factory.hpp"
2
3 #include "metric.hpp"
4 #include "report.hpp"
5 #include "sensor.hpp"
6 #include "utils/clock.hpp"
7 #include "utils/conversion.hpp"
8 #include "utils/dbus_mapper.hpp"
9 #include "utils/transform.hpp"
10
ReportFactory(std::shared_ptr<sdbusplus::asio::connection> bus,const std::shared_ptr<sdbusplus::asio::object_server> & objServer,SensorCache & sensorCache)11 ReportFactory::ReportFactory(
12 std::shared_ptr<sdbusplus::asio::connection> bus,
13 const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
14 SensorCache& sensorCache) :
15 bus(std::move(bus)), objServer(objServer), sensorCache(sensorCache)
16 {}
17
make(const std::string & id,const std::string & name,const ReportingType reportingType,const std::vector<ReportAction> & reportActions,Milliseconds period,uint64_t appendLimit,const ReportUpdates reportUpdates,interfaces::ReportManager & reportManager,interfaces::JsonStorage & reportStorage,std::vector<LabeledMetricParameters> labeledMetricParams,bool enabled,Readings readings) const18 std::unique_ptr<interfaces::Report> ReportFactory::make(
19 const std::string& id, const std::string& name,
20 const ReportingType reportingType,
21 const std::vector<ReportAction>& reportActions, Milliseconds period,
22 uint64_t appendLimit, const ReportUpdates reportUpdates,
23 interfaces::ReportManager& reportManager,
24 interfaces::JsonStorage& reportStorage,
25 std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
26 Readings readings) const
27 {
28 auto metrics = utils::transform(
29 labeledMetricParams,
30 [this](const LabeledMetricParameters& param)
31 -> std::shared_ptr<interfaces::Metric> {
32 namespace ts = utils::tstring;
33
34 return std::make_shared<Metric>(
35 getSensors(param.at_label<ts::SensorPath>()),
36 param.at_label<ts::OperationType>(),
37 param.at_label<ts::CollectionTimeScope>(),
38 param.at_label<ts::CollectionDuration>(),
39 std::make_unique<Clock>());
40 });
41
42 return std::make_unique<Report>(
43 bus->get_io_context(), objServer, id, name, reportingType,
44 reportActions, period, appendLimit, reportUpdates, reportManager,
45 reportStorage, std::move(metrics), *this, enabled,
46 std::make_unique<Clock>(), std::move(readings));
47 }
48
updateMetrics(std::vector<std::shared_ptr<interfaces::Metric>> & metrics,bool enabled,const std::vector<LabeledMetricParameters> & labeledMetricParams) const49 void ReportFactory::updateMetrics(
50 std::vector<std::shared_ptr<interfaces::Metric>>& metrics, bool enabled,
51 const std::vector<LabeledMetricParameters>& labeledMetricParams) const
52 {
53 std::vector<std::shared_ptr<interfaces::Metric>> oldMetrics = metrics;
54 std::vector<std::shared_ptr<interfaces::Metric>> newMetrics;
55
56 for (const auto& labeledMetricParam : labeledMetricParams)
57 {
58 auto existing = std::find_if(oldMetrics.begin(), oldMetrics.end(),
59 [labeledMetricParam](auto metric) {
60 return labeledMetricParam ==
61 metric->dumpConfiguration();
62 });
63
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>(),
75 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);
94 }
95
getSensors(const std::vector<LabeledSensorInfo> & sensorPaths) const96 Sensors ReportFactory::getSensors(
97 const std::vector<LabeledSensorInfo>& sensorPaths) const
98 {
99 using namespace utils::tstring;
100
101 return utils::transform(
102 sensorPaths,
103 [this](const LabeledSensorInfo& sensorPath)
104 -> 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 });
109 }
110
convertMetricParams(boost::asio::yield_context & yield,const ReadingParameters & metricParams) const111 std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
112 boost::asio::yield_context& yield,
113 const ReadingParameters& metricParams) const
114 {
115 if (metricParams.empty())
116 {
117 return {};
118 }
119
120 auto tree = utils::getSubTreeSensors(yield, bus);
121 return getMetricParamsFromSensorTree(metricParams, tree);
122 }
123
convertMetricParams(const ReadingParameters & metricParams) const124 std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
125 const ReadingParameters& metricParams) const
126 {
127 if (metricParams.empty())
128 {
129 return {};
130 }
131
132 auto tree = utils::getSubTreeSensors(bus);
133 return getMetricParamsFromSensorTree(metricParams, tree);
134 }
135
136 std::vector<LabeledMetricParameters>
getMetricParamsFromSensorTree(const ReadingParameters & metricParams,const std::vector<utils::SensorTree> & tree) const137 ReportFactory::getMetricParamsFromSensorTree(
138 const ReadingParameters& metricParams,
139 const std::vector<utils::SensorTree>& tree) const
140 {
141 try
142 {
143 return utils::transform(metricParams, [&tree](const auto& item) {
144 auto [sensorPaths, operationType, collectionTimeScope,
145 collectionDuration] = item;
146
147 std::vector<LabeledSensorInfo> sensorParameters;
148
149 for (const auto& [sensorPath, metadata] : sensorPaths)
150 {
151 auto it = std::find_if(tree.begin(), tree.end(),
152 [path = sensorPath](const auto& v) {
153 return v.first == path;
154 });
155
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 }
162 }
163
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),
189 utils::toOperationType(operationType),
190 utils::toCollectionTimeScope(collectionTimeScope),
191 CollectionDuration(Milliseconds(collectionDuration)));
192 });
193 }
194 catch (const errors::InvalidArgument& e)
195 {
196 if (e.propertyName == "ReadingParameters")
197 {
198 throw;
199 }
200
201 using namespace std::literals::string_literals;
202 throw errors::InvalidArgument("ReadingParameters."s + e.propertyName);
203 }
204 }
205