1 #include "report.hpp" 2 3 #include "report_manager.hpp" 4 5 #include <numeric> 6 7 Report::Report(boost::asio::io_context& ioc, 8 const std::shared_ptr<sdbusplus::asio::object_server>& objServer, 9 const std::string& reportName, const std::string& reportingType, 10 const bool emitsReadingsSignal, 11 const bool logToMetricReportsCollection, 12 const std::chrono::milliseconds period, 13 const ReadingParameters& metricParams, 14 interfaces::ReportManager& reportManager, 15 std::vector<std::shared_ptr<interfaces::Metric>> metrics) : 16 name(reportName), 17 path(reportDir + name), interval(period), objServer(objServer), 18 metrics(std::move(metrics)), timer(ioc) 19 { 20 reportIface = objServer->add_unique_interface( 21 path, reportIfaceName, 22 [this, &reportingType, &emitsReadingsSignal, 23 &logToMetricReportsCollection, &metricParams](auto& dbusIface) { 24 dbusIface.register_property( 25 "Interval", static_cast<uint64_t>(interval.count()), 26 [this](const uint64_t newVal, uint64_t& actualVal) { 27 std::chrono::milliseconds newValT(newVal); 28 if (newValT < ReportManager::minInterval) 29 { 30 return false; 31 } 32 actualVal = newVal; 33 interval = newValT; 34 return true; 35 }); 36 dbusIface.register_property("Persistency", bool{false}); 37 dbusIface.register_property_r( 38 "Readings", readings, 39 sdbusplus::vtable::property_::emits_change, 40 [this](const auto&) { return readings; }); 41 dbusIface.register_property("ReportingType", reportingType); 42 dbusIface.register_property("ReadingParameters", metricParams); 43 dbusIface.register_property("EmitsReadingsUpdate", 44 emitsReadingsSignal); 45 dbusIface.register_property("LogToMetricReportsCollection", 46 logToMetricReportsCollection); 47 }); 48 49 deleteIface = objServer->add_unique_interface( 50 path, deleteIfaceName, [this, &ioc, &reportManager](auto& dbusIface) { 51 dbusIface.register_method("Delete", [this, &ioc, &reportManager] { 52 boost::asio::post(ioc, [this, &reportManager] { 53 reportManager.removeReport(this); 54 }); 55 }); 56 }); 57 58 if (reportingType == "Periodic") 59 { 60 scheduleTimer(interval); 61 } 62 } 63 64 void Report::timerProc(boost::system::error_code ec, Report& self) 65 { 66 if (ec) 67 { 68 return; 69 } 70 71 self.updateReadings(); 72 self.scheduleTimer(self.interval); 73 } 74 75 void Report::scheduleTimer(std::chrono::milliseconds timerInterval) 76 { 77 timer.expires_after(timerInterval); 78 timer.async_wait( 79 [this](boost::system::error_code ec) { timerProc(ec, *this); }); 80 } 81 82 void Report::updateReadings() 83 { 84 auto numElements = std::accumulate( 85 metrics.begin(), metrics.end(), 0u, [](auto sum, const auto& metric) { 86 return sum + metric->getReadings().size(); 87 }); 88 89 readingsCache.resize(numElements); 90 91 auto it = readingsCache.begin(); 92 93 for (const auto& metric : metrics) 94 { 95 for (const auto& reading : metric->getReadings()) 96 { 97 *(it++) = std::make_tuple(reading.id, reading.metadata, 98 reading.value, reading.timestamp); 99 } 100 } 101 102 std::get<0>(readings) = std::time(0); 103 std::get<1>(readings) = readingsCache; 104 reportIface->signal_property("Readings"); 105 } 106