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 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)), 16 objServer(objServer), sensorCache(sensorCache) 17 {} 18 19 std::unique_ptr<interfaces::Report> ReportFactory::make( 20 const std::string& id, const std::string& name, 21 const ReportingType reportingType, 22 const std::vector<ReportAction>& reportActions, Milliseconds period, 23 uint64_t appendLimit, const ReportUpdates reportUpdates, 24 interfaces::ReportManager& reportManager, 25 interfaces::JsonStorage& reportStorage, 26 std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled, 27 Readings readings) const 28 { 29 auto metrics = utils::transform(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 49 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 == metric->dumpConfiguration(); 61 }); 62 63 if (existing != oldMetrics.end()) 64 { 65 newMetrics.emplace_back(*existing); 66 oldMetrics.erase(existing); 67 continue; 68 } 69 70 namespace ts = utils::tstring; 71 newMetrics.emplace_back(std::make_shared<Metric>( 72 getSensors(labeledMetricParam.at_label<ts::SensorPath>()), 73 labeledMetricParam.at_label<ts::OperationType>(), 74 labeledMetricParam.at_label<ts::CollectionTimeScope>(), 75 labeledMetricParam.at_label<ts::CollectionDuration>(), 76 std::make_unique<Clock>())); 77 78 if (enabled) 79 { 80 newMetrics.back()->initialize(); 81 } 82 } 83 84 if (enabled) 85 { 86 for (auto& metric : oldMetrics) 87 { 88 metric->deinitialize(); 89 } 90 } 91 92 metrics = std::move(newMetrics); 93 } 94 95 Sensors ReportFactory::getSensors( 96 const std::vector<LabeledSensorInfo>& sensorPaths) const 97 { 98 using namespace utils::tstring; 99 100 return utils::transform(sensorPaths, 101 [this](const LabeledSensorInfo& sensorPath) 102 -> std::shared_ptr<interfaces::Sensor> { 103 return sensorCache.makeSensor<Sensor>( 104 sensorPath.at_label<Service>(), sensorPath.at_label<Path>(), 105 sensorPath.at_label<Metadata>(), bus->get_io_context(), bus); 106 }); 107 } 108 109 std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams( 110 boost::asio::yield_context& yield, 111 const ReadingParameters& metricParams) const 112 { 113 if (metricParams.empty()) 114 { 115 return {}; 116 } 117 118 auto tree = utils::getSubTreeSensors(yield, bus); 119 return getMetricParamsFromSensorTree(metricParams, tree); 120 } 121 122 std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams( 123 const ReadingParameters& metricParams) const 124 { 125 if (metricParams.empty()) 126 { 127 return {}; 128 } 129 130 auto tree = utils::getSubTreeSensors(bus); 131 return getMetricParamsFromSensorTree(metricParams, tree); 132 } 133 134 std::vector<LabeledMetricParameters> 135 ReportFactory::getMetricParamsFromSensorTree( 136 const ReadingParameters& metricParams, 137 const std::vector<utils::SensorTree>& tree) const 138 { 139 try 140 { 141 return utils::transform(metricParams, [&tree](const auto& item) { 142 auto [sensorPaths, operationType, collectionTimeScope, 143 collectionDuration] = item; 144 145 std::vector<LabeledSensorInfo> sensorParameters; 146 147 for (const auto& [sensorPath, metadata] : sensorPaths) 148 { 149 auto it = std::find_if(tree.begin(), tree.end(), 150 [path = sensorPath](const auto& v) { 151 return v.first == path; 152 }); 153 154 if (it != tree.end() && it->second.size() == 1) 155 { 156 const auto& [service, ifaces] = it->second.front(); 157 sensorParameters.emplace_back(service, sensorPath, 158 metadata); 159 } 160 } 161 162 if (sensorParameters.size() != sensorPaths.size()) 163 { 164 throw errors::InvalidArgument("ReadingParameters", 165 "Service not found."); 166 } 167 168 if (operationType.empty()) 169 { 170 operationType = utils::enumToString(OperationType::avg); 171 } 172 else if (operationType == "SINGLE") 173 { 174 operationType = utils::enumToString(OperationType::avg); 175 collectionTimeScope = 176 utils::enumToString(CollectionTimeScope::point); 177 } 178 179 if (collectionTimeScope.empty()) 180 { 181 collectionTimeScope = 182 utils::enumToString(CollectionTimeScope::point); 183 } 184 185 return LabeledMetricParameters( 186 std::move(sensorParameters), 187 utils::toOperationType(operationType), 188 utils::toCollectionTimeScope(collectionTimeScope), 189 CollectionDuration(Milliseconds(collectionDuration))); 190 }); 191 } 192 catch (const errors::InvalidArgument& e) 193 { 194 if (e.propertyName == "ReadingParameters") 195 { 196 throw; 197 } 198 199 using namespace std::literals::string_literals; 200 throw errors::InvalidArgument("ReadingParameters."s + e.propertyName); 201 } 202 } 203