164b75a5bSKrzysztof Grobelny #include "report_manager.hpp"
264b75a5bSKrzysztof Grobelny
3e2362796SWludzik, Jozef #include "report.hpp"
4dcc4e193SKrzysztof Grobelny #include "types/report_types.hpp"
5e8fc5751SKrzysztof Grobelny #include "utils/conversion.hpp"
632305f14SSzymon Dompke #include "utils/dbus_path_utils.hpp"
732305f14SSzymon Dompke #include "utils/make_id_name.hpp"
8d2238194SKrzysztof Grobelny #include "utils/transform.hpp"
9e2362796SWludzik, Jozef
10e2362796SWludzik, Jozef #include <phosphor-logging/log.hpp>
11cb88cfdfSWludzik, Jozef #include <sdbusplus/exception.hpp>
12a8182bebSKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
13cb88cfdfSWludzik, Jozef
14a8182bebSKrzysztof Grobelny #include <optional>
15e2362796SWludzik, Jozef #include <stdexcept>
1664b75a5bSKrzysztof Grobelny #include <system_error>
1764b75a5bSKrzysztof Grobelny
ReportManager(std::unique_ptr<interfaces::ReportFactory> reportFactoryIn,std::unique_ptr<interfaces::JsonStorage> reportStorageIn,const std::shared_ptr<sdbusplus::asio::object_server> & objServerIn)1864b75a5bSKrzysztof Grobelny ReportManager::ReportManager(
192f9f9b87SWludzik, Jozef std::unique_ptr<interfaces::ReportFactory> reportFactoryIn,
20e2362796SWludzik, Jozef std::unique_ptr<interfaces::JsonStorage> reportStorageIn,
21e6d48874SKrzysztof Grobelny const std::shared_ptr<sdbusplus::asio::object_server>& objServerIn) :
222f9f9b87SWludzik, Jozef reportFactory(std::move(reportFactoryIn)),
23e6d48874SKrzysztof Grobelny reportStorage(std::move(reportStorageIn)), objServer(objServerIn)
2464b75a5bSKrzysztof Grobelny {
25cb88cfdfSWludzik, Jozef reports.reserve(maxReports);
266ccfcbf5SKrzysztof Grobelny
27e2362796SWludzik, Jozef loadFromPersistent();
2864b75a5bSKrzysztof Grobelny
29cb88cfdfSWludzik, Jozef reportManagerIface = objServer->add_unique_interface(
30*c7935fa1SPatrick Williams reportManagerPath, reportManagerIfaceName, [this](auto& dbusIface) {
313a1c297aSPatrick Williams dbusIface.register_property_r("MaxReports", size_t{},
323a1c297aSPatrick Williams sdbusplus::vtable::property_::const_,
3364b75a5bSKrzysztof Grobelny [](const auto&) { return maxReports; });
34cb88cfdfSWludzik, Jozef dbusIface.register_property_r(
3564b75a5bSKrzysztof Grobelny "MinInterval", uint64_t{}, sdbusplus::vtable::property_::const_,
3664b75a5bSKrzysztof Grobelny [](const auto&) -> uint64_t { return minInterval.count(); });
3760fee077SKrzysztof Grobelny dbusIface.register_property_r(
3860fee077SKrzysztof Grobelny "SupportedOperationTypes", std::vector<std::string>{},
3960fee077SKrzysztof Grobelny sdbusplus::vtable::property_::const_,
4060fee077SKrzysztof Grobelny [](const auto&) -> std::vector<std::string> {
41fdb06a14SSzymon Dompke return utils::transform<std::vector>(
423a1c297aSPatrick Williams utils::convDataOperationType,
433a1c297aSPatrick Williams [](const auto& item) { return std::string(item.first); });
4460fee077SKrzysztof Grobelny });
45cb88cfdfSWludzik, Jozef dbusIface.register_method(
463a1c297aSPatrick Williams "AddReport",
47cff70c14SKrzysztof Grobelny [this](boost::asio::yield_context& yield, std::string reportId,
48cff70c14SKrzysztof Grobelny std::string reportName, std::string reportingType,
49cff70c14SKrzysztof Grobelny std::string reportUpdates, uint64_t appendLimit,
50cff70c14SKrzysztof Grobelny std::vector<std::string> reportActions, uint64_t interval,
51cff70c14SKrzysztof Grobelny ReadingParameters readingParameters, bool enabled) {
52cff70c14SKrzysztof Grobelny if (reportingType.empty())
5351497a0cSKrzysztof Grobelny {
54cff70c14SKrzysztof Grobelny reportingType = utils::enumToString(ReportingType::onRequest);
5551497a0cSKrzysztof Grobelny }
5651497a0cSKrzysztof Grobelny
57cff70c14SKrzysztof Grobelny if (reportUpdates.empty())
5862c08e9bSKrzysztof Grobelny {
59cff70c14SKrzysztof Grobelny reportUpdates = utils::enumToString(ReportUpdates::overwrite);
6062c08e9bSKrzysztof Grobelny }
6162c08e9bSKrzysztof Grobelny
62cff70c14SKrzysztof Grobelny if (appendLimit == std::numeric_limits<uint64_t>::max())
6362c08e9bSKrzysztof Grobelny {
64cff70c14SKrzysztof Grobelny appendLimit = maxAppendLimit;
6562c08e9bSKrzysztof Grobelny }
66a8182bebSKrzysztof Grobelny
67cff70c14SKrzysztof Grobelny if (interval == std::numeric_limits<uint64_t>::max())
68cff70c14SKrzysztof Grobelny {
69cff70c14SKrzysztof Grobelny interval = 0;
70cff70c14SKrzysztof Grobelny }
71cff70c14SKrzysztof Grobelny
72cff70c14SKrzysztof Grobelny return addReport(yield, reportId, reportName,
73cff70c14SKrzysztof Grobelny utils::toReportingType(reportingType),
74*c7935fa1SPatrick Williams utils::transform(reportActions,
7551497a0cSKrzysztof Grobelny [](const auto& reportAction) {
763a1c297aSPatrick Williams return utils::toReportAction(reportAction);
7751497a0cSKrzysztof Grobelny }),
78cff70c14SKrzysztof Grobelny Milliseconds(interval), appendLimit,
79cff70c14SKrzysztof Grobelny utils::toReportUpdates(reportUpdates),
80cff70c14SKrzysztof Grobelny readingParameters, enabled)
81d2238194SKrzysztof Grobelny .getPath();
82e2362796SWludzik, Jozef });
83e2362796SWludzik, Jozef });
84e2362796SWludzik, Jozef }
85e2362796SWludzik, Jozef
removeReport(const interfaces::Report * report)86e2362796SWludzik, Jozef void ReportManager::removeReport(const interfaces::Report* report)
87e2362796SWludzik, Jozef {
88e2362796SWludzik, Jozef reports.erase(
89e2362796SWludzik, Jozef std::remove_if(reports.begin(), reports.end(),
90e2362796SWludzik, Jozef [report](const auto& x) { return report == x.get(); }),
91e2362796SWludzik, Jozef reports.end());
92e2362796SWludzik, Jozef }
93e2362796SWludzik, Jozef
verifyAddReport(const std::string & reportId,const std::string & reportName,const ReportingType reportingType,Milliseconds interval,const ReportUpdates reportUpdates,const uint64_t appendLimit,const std::vector<LabeledMetricParameters> & readingParams)94dcc4e193SKrzysztof Grobelny void ReportManager::verifyAddReport(
95b8cc78ddSKrzysztof Grobelny const std::string& reportId, const std::string& reportName,
96b8cc78ddSKrzysztof Grobelny const ReportingType reportingType, Milliseconds interval,
97cd5b0b7eSAnkita Vilas Gawade const ReportUpdates reportUpdates, const uint64_t appendLimit,
98dcc4e193SKrzysztof Grobelny const std::vector<LabeledMetricParameters>& readingParams)
99e2362796SWludzik, Jozef {
10032305f14SSzymon Dompke namespace ts = utils::tstring;
10132305f14SSzymon Dompke
102cb88cfdfSWludzik, Jozef if (reports.size() >= maxReports)
103cb88cfdfSWludzik, Jozef {
104cb88cfdfSWludzik, Jozef throw sdbusplus::exception::SdBusError(
105cb88cfdfSWludzik, Jozef static_cast<int>(std::errc::too_many_files_open),
106cb88cfdfSWludzik, Jozef "Reached maximal report count");
10764b75a5bSKrzysztof Grobelny }
10864b75a5bSKrzysztof Grobelny
109e6c417cfSKrzysztof Grobelny if (appendLimit > maxAppendLimit &&
110e6c417cfSKrzysztof Grobelny appendLimit != std::numeric_limits<uint64_t>::max())
111cd5b0b7eSAnkita Vilas Gawade {
11262c08e9bSKrzysztof Grobelny throw errors::InvalidArgument("AppendLimit", "Out of range.");
113cd5b0b7eSAnkita Vilas Gawade }
114cd5b0b7eSAnkita Vilas Gawade
115973b4bb0SKrzysztof Grobelny if ((reportingType == ReportingType::periodic && interval < minInterval) ||
116973b4bb0SKrzysztof Grobelny (reportingType != ReportingType::periodic &&
117973b4bb0SKrzysztof Grobelny interval != Milliseconds{0}))
118cb88cfdfSWludzik, Jozef {
11962c08e9bSKrzysztof Grobelny throw errors::InvalidArgument("Interval");
120cb88cfdfSWludzik, Jozef }
121bc766b4dSWludzik, Jozef
122cd5b0b7eSAnkita Vilas Gawade size_t metricCount = 0;
123cd5b0b7eSAnkita Vilas Gawade for (auto metricParam : readingParams)
124cd5b0b7eSAnkita Vilas Gawade {
125cd5b0b7eSAnkita Vilas Gawade auto metricParamsVec =
126cd5b0b7eSAnkita Vilas Gawade metricParam.at_label<utils::tstring::SensorPath>();
127cd5b0b7eSAnkita Vilas Gawade metricCount += metricParamsVec.size();
128cd5b0b7eSAnkita Vilas Gawade }
129e8fc5751SKrzysztof Grobelny
130cd5b0b7eSAnkita Vilas Gawade if (readingParams.size() > maxNumberMetrics ||
131cd5b0b7eSAnkita Vilas Gawade metricCount > maxNumberMetrics)
132bc766b4dSWludzik, Jozef {
13362c08e9bSKrzysztof Grobelny throw errors::InvalidArgument("MetricParams", "Too many.");
134bc766b4dSWludzik, Jozef }
135e8fc5751SKrzysztof Grobelny
136dcc4e193SKrzysztof Grobelny for (const LabeledMetricParameters& item : readingParams)
137e8fc5751SKrzysztof Grobelny {
138dcc4e193SKrzysztof Grobelny utils::toOperationType(
139dcc4e193SKrzysztof Grobelny utils::toUnderlying(item.at_label<ts::OperationType>()));
140e8fc5751SKrzysztof Grobelny }
141e8fc5751SKrzysztof Grobelny }
142cb88cfdfSWludzik, Jozef
addReport(boost::asio::yield_context & yield,const std::string & reportId,const std::string & reportName,const ReportingType reportingType,const std::vector<ReportAction> & reportActions,Milliseconds interval,const uint64_t appendLimit,const ReportUpdates reportUpdates,ReadingParameters metricParams,const bool enabled)143d2238194SKrzysztof Grobelny interfaces::Report& ReportManager::addReport(
144b8cc78ddSKrzysztof Grobelny boost::asio::yield_context& yield, const std::string& reportId,
145b8cc78ddSKrzysztof Grobelny const std::string& reportName, const ReportingType reportingType,
14651497a0cSKrzysztof Grobelny const std::vector<ReportAction>& reportActions, Milliseconds interval,
14751497a0cSKrzysztof Grobelny const uint64_t appendLimit, const ReportUpdates reportUpdates,
1487e098e93SLukasz Kazmierczak ReadingParameters metricParams, const bool enabled)
149d2238194SKrzysztof Grobelny {
1503a1c297aSPatrick Williams auto labeledMetricParams = reportFactory->convertMetricParams(yield,
1513a1c297aSPatrick Williams metricParams);
152d2238194SKrzysztof Grobelny
153b8cc78ddSKrzysztof Grobelny return addReport(reportId, reportName, reportingType, reportActions,
154b8cc78ddSKrzysztof Grobelny interval, appendLimit, reportUpdates,
155493e62ebSKrzysztof Grobelny std::move(labeledMetricParams), enabled, Readings{});
156d2238194SKrzysztof Grobelny }
157d2238194SKrzysztof Grobelny
addReport(const std::string & reportId,const std::string & reportName,const ReportingType reportingType,const std::vector<ReportAction> & reportActions,Milliseconds interval,const uint64_t appendLimit,const ReportUpdates reportUpdates,std::vector<LabeledMetricParameters> labeledMetricParams,const bool enabled,Readings readings)158d2238194SKrzysztof Grobelny interfaces::Report& ReportManager::addReport(
159b8cc78ddSKrzysztof Grobelny const std::string& reportId, const std::string& reportName,
160b8cc78ddSKrzysztof Grobelny const ReportingType reportingType,
16151497a0cSKrzysztof Grobelny const std::vector<ReportAction>& reportActions, Milliseconds interval,
16251497a0cSKrzysztof Grobelny const uint64_t appendLimit, const ReportUpdates reportUpdates,
1637e098e93SLukasz Kazmierczak std::vector<LabeledMetricParameters> labeledMetricParams,
164493e62ebSKrzysztof Grobelny const bool enabled, Readings readings)
165d2238194SKrzysztof Grobelny {
166b8cc78ddSKrzysztof Grobelny const auto existingReportIds = utils::transform(
167b8cc78ddSKrzysztof Grobelny reports, [](const auto& report) { return report->getId(); });
168b8cc78ddSKrzysztof Grobelny
16932305f14SSzymon Dompke auto [id, name] = utils::makeIdName(reportId, reportName, reportNameDefault,
17032305f14SSzymon Dompke existingReportIds);
171b8cc78ddSKrzysztof Grobelny
172b8cc78ddSKrzysztof Grobelny verifyAddReport(id, name, reportingType, interval, reportUpdates,
173cd5b0b7eSAnkita Vilas Gawade appendLimit, labeledMetricParams);
174d2238194SKrzysztof Grobelny
175493e62ebSKrzysztof Grobelny reports.emplace_back(
176493e62ebSKrzysztof Grobelny reportFactory->make(id, name, reportingType, reportActions, interval,
177493e62ebSKrzysztof Grobelny appendLimit, reportUpdates, *this, *reportStorage,
178493e62ebSKrzysztof Grobelny labeledMetricParams, enabled, std::move(readings)));
179d2238194SKrzysztof Grobelny return *reports.back();
180cb88cfdfSWludzik, Jozef }
181cb88cfdfSWludzik, Jozef
loadFromPersistent()182e2362796SWludzik, Jozef void ReportManager::loadFromPersistent()
183cb88cfdfSWludzik, Jozef {
184e2362796SWludzik, Jozef std::vector<interfaces::JsonStorage::FilePath> paths =
185e2362796SWludzik, Jozef reportStorage->list();
186e2362796SWludzik, Jozef
187e2362796SWludzik, Jozef for (const auto& path : paths)
188e2362796SWludzik, Jozef {
189e2362796SWludzik, Jozef std::optional<nlohmann::json> data = reportStorage->load(path);
190e2362796SWludzik, Jozef try
191e2362796SWludzik, Jozef {
192e2362796SWludzik, Jozef size_t version = data->at("Version").get<size_t>();
193e2362796SWludzik, Jozef if (version != Report::reportVersion)
194e2362796SWludzik, Jozef {
195e2362796SWludzik, Jozef throw std::logic_error("Invalid version");
196e2362796SWludzik, Jozef }
197b8cc78ddSKrzysztof Grobelny bool enabled = data->at("Enabled").get<bool>();
198b8cc78ddSKrzysztof Grobelny std::string& id = data->at("Id").get_ref<std::string&>();
199e2362796SWludzik, Jozef std::string& name = data->at("Name").get_ref<std::string&>();
20051497a0cSKrzysztof Grobelny
20151497a0cSKrzysztof Grobelny uint32_t reportingType = data->at("ReportingType").get<uint32_t>();
20251497a0cSKrzysztof Grobelny std::vector<ReportAction> reportActions = utils::transform(
20351497a0cSKrzysztof Grobelny data->at("ReportActions").get<std::vector<uint32_t>>(),
20451497a0cSKrzysztof Grobelny [](const auto reportAction) {
20551497a0cSKrzysztof Grobelny return utils::toReportAction(reportAction);
20651497a0cSKrzysztof Grobelny });
207e2362796SWludzik, Jozef uint64_t interval = data->at("Interval").get<uint64_t>();
2083eb56865SSzymon Dompke uint64_t appendLimit = data->at("AppendLimit").get<uint64_t>();
20951497a0cSKrzysztof Grobelny uint32_t reportUpdates = data->at("ReportUpdates").get<uint32_t>();
210d2238194SKrzysztof Grobelny auto readingParameters =
211d2238194SKrzysztof Grobelny data->at("ReadingParameters")
212d2238194SKrzysztof Grobelny .get<std::vector<LabeledMetricParameters>>();
213e2362796SWludzik, Jozef
214493e62ebSKrzysztof Grobelny Readings readings = {};
215493e62ebSKrzysztof Grobelny
216493e62ebSKrzysztof Grobelny if (auto it = data->find("MetricValues"); it != data->end())
217493e62ebSKrzysztof Grobelny {
218493e62ebSKrzysztof Grobelny const auto labeledReadings = it->get<LabeledReadings>();
219493e62ebSKrzysztof Grobelny readings = utils::toReadings(labeledReadings);
220493e62ebSKrzysztof Grobelny }
221493e62ebSKrzysztof Grobelny
222b8cc78ddSKrzysztof Grobelny addReport(id, name, utils::toReportingType(reportingType),
22351497a0cSKrzysztof Grobelny reportActions, Milliseconds(interval), appendLimit,
22451497a0cSKrzysztof Grobelny utils::toReportUpdates(reportUpdates),
225493e62ebSKrzysztof Grobelny std::move(readingParameters), enabled,
226493e62ebSKrzysztof Grobelny std::move(readings));
227e2362796SWludzik, Jozef }
228e2362796SWludzik, Jozef catch (const std::exception& e)
229e2362796SWludzik, Jozef {
230e2362796SWludzik, Jozef phosphor::logging::log<phosphor::logging::level::ERR>(
231e2362796SWludzik, Jozef "Failed to load report from storage",
232e2362796SWludzik, Jozef phosphor::logging::entry(
233982c5b5bSWludzik, Jozef "FILENAME=%s",
234e2362796SWludzik, Jozef static_cast<std::filesystem::path>(path).c_str()),
235982c5b5bSWludzik, Jozef phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
236e2362796SWludzik, Jozef reportStorage->remove(path);
237e2362796SWludzik, Jozef }
238e2362796SWludzik, Jozef }
23964b75a5bSKrzysztof Grobelny }
240