blob: 3af033aae9b1da4fa28dbf30a4cb2a43f2eedcd8 [file] [log] [blame]
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +02001#include "report_manager.hpp"
2
Wludzik, Jozefe2362792020-10-27 17:23:55 +01003#include "report.hpp"
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +00004#include "types/report_types.hpp"
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +00005#include "utils/conversion.hpp"
Szymon Dompke32305f12022-07-05 15:37:21 +02006#include "utils/dbus_path_utils.hpp"
7#include "utils/make_id_name.hpp"
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +00008#include "utils/transform.hpp"
Wludzik, Jozefe2362792020-10-27 17:23:55 +01009
10#include <phosphor-logging/log.hpp>
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020011#include <sdbusplus/exception.hpp>
Krzysztof Grobelnya8182be2022-07-04 11:26:20 +020012#include <sdbusplus/unpack_properties.hpp>
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020013
Krzysztof Grobelnya8182be2022-07-04 11:26:20 +020014#include <optional>
Wludzik, Jozefe2362792020-10-27 17:23:55 +010015#include <stdexcept>
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020016#include <system_error>
17
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020018ReportManager::ReportManager(
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020019 std::unique_ptr<interfaces::ReportFactory> reportFactoryIn,
Wludzik, Jozefe2362792020-10-27 17:23:55 +010020 std::unique_ptr<interfaces::JsonStorage> reportStorageIn,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010021 const std::shared_ptr<sdbusplus::asio::object_server>& objServerIn) :
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020022 reportFactory(std::move(reportFactoryIn)),
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010023 reportStorage(std::move(reportStorageIn)), objServer(objServerIn)
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020024{
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020025 reports.reserve(maxReports);
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010026
Wludzik, Jozefe2362792020-10-27 17:23:55 +010027 loadFromPersistent();
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020028
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020029 reportManagerIface = objServer->add_unique_interface(
Patrick Williamsc7935fa2023-10-20 11:19:30 -050030 reportManagerPath, reportManagerIfaceName, [this](auto& dbusIface) {
Patrick Williams3a1c2972023-05-10 07:51:04 -050031 dbusIface.register_property_r("MaxReports", size_t{},
32 sdbusplus::vtable::property_::const_,
33 [](const auto&) { return maxReports; });
34 dbusIface.register_property_r(
35 "MinInterval", uint64_t{}, sdbusplus::vtable::property_::const_,
36 [](const auto&) -> uint64_t { return minInterval.count(); });
37 dbusIface.register_property_r(
38 "SupportedOperationTypes", std::vector<std::string>{},
39 sdbusplus::vtable::property_::const_,
40 [](const auto&) -> std::vector<std::string> {
Patrick Williamsc7935fa2023-10-20 11:19:30 -050041 return utils::transform<std::vector>(
42 utils::convDataOperationType,
43 [](const auto& item) { return std::string(item.first); });
44 });
Patrick Williams3a1c2972023-05-10 07:51:04 -050045 dbusIface.register_method(
46 "AddReport",
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000047 [this](boost::asio::yield_context& yield, std::string reportId,
48 std::string reportName, std::string reportingType,
49 std::string reportUpdates, uint64_t appendLimit,
50 std::vector<std::string> reportActions, uint64_t interval,
51 ReadingParameters readingParameters, bool enabled) {
52 if (reportingType.empty())
Patrick Williams3a1c2972023-05-10 07:51:04 -050053 {
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000054 reportingType = utils::enumToString(ReportingType::onRequest);
Patrick Williams3a1c2972023-05-10 07:51:04 -050055 }
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010056
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000057 if (reportUpdates.empty())
Patrick Williams3a1c2972023-05-10 07:51:04 -050058 {
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000059 reportUpdates = utils::enumToString(ReportUpdates::overwrite);
Patrick Williams3a1c2972023-05-10 07:51:04 -050060 }
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +020061
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000062 if (appendLimit == std::numeric_limits<uint64_t>::max())
Patrick Williams3a1c2972023-05-10 07:51:04 -050063 {
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000064 appendLimit = maxAppendLimit;
Patrick Williams3a1c2972023-05-10 07:51:04 -050065 }
Krzysztof Grobelnya8182be2022-07-04 11:26:20 +020066
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000067 if (interval == std::numeric_limits<uint64_t>::max())
68 {
69 interval = 0;
70 }
71
72 return addReport(yield, reportId, reportName,
73 utils::toReportingType(reportingType),
Patrick Williamsc7935fa2023-10-20 11:19:30 -050074 utils::transform(reportActions,
75 [](const auto& reportAction) {
Patrick Williams3a1c2972023-05-10 07:51:04 -050076 return utils::toReportAction(reportAction);
Patrick Williamsc7935fa2023-10-20 11:19:30 -050077 }),
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000078 Milliseconds(interval), appendLimit,
79 utils::toReportUpdates(reportUpdates),
80 readingParameters, enabled)
Patrick Williams3a1c2972023-05-10 07:51:04 -050081 .getPath();
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020082 });
Patrick Williamsc7935fa2023-10-20 11:19:30 -050083 });
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020084}
85
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020086void ReportManager::removeReport(const interfaces::Report* report)
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020087{
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020088 reports.erase(
89 std::remove_if(reports.begin(), reports.end(),
90 [report](const auto& x) { return report == x.get(); }),
91 reports.end());
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020092}
Wludzik, Jozefe2362792020-10-27 17:23:55 +010093
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000094void ReportManager::verifyAddReport(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010095 const std::string& reportId, const std::string& reportName,
96 const ReportingType reportingType, Milliseconds interval,
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +000097 const ReportUpdates reportUpdates, const uint64_t appendLimit,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000098 const std::vector<LabeledMetricParameters>& readingParams)
Wludzik, Jozefe2362792020-10-27 17:23:55 +010099{
Szymon Dompke32305f12022-07-05 15:37:21 +0200100 namespace ts = utils::tstring;
101
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100102 if (reports.size() >= maxReports)
103 {
104 throw sdbusplus::exception::SdBusError(
105 static_cast<int>(std::errc::too_many_files_open),
106 "Reached maximal report count");
107 }
108
Krzysztof Grobelnye6c417c2022-02-02 17:25:53 +0100109 if (appendLimit > maxAppendLimit &&
110 appendLimit != std::numeric_limits<uint64_t>::max())
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +0000111 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200112 throw errors::InvalidArgument("AppendLimit", "Out of range.");
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +0000113 }
114
Krzysztof Grobelny973b4bb2022-04-25 17:07:27 +0200115 if ((reportingType == ReportingType::periodic && interval < minInterval) ||
116 (reportingType != ReportingType::periodic &&
117 interval != Milliseconds{0}))
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100118 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200119 throw errors::InvalidArgument("Interval");
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100120 }
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100121
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +0000122 size_t metricCount = 0;
123 for (auto metricParam : readingParams)
124 {
125 auto metricParamsVec =
126 metricParam.at_label<utils::tstring::SensorPath>();
127 metricCount += metricParamsVec.size();
128 }
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000129
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +0000130 if (readingParams.size() > maxNumberMetrics ||
131 metricCount > maxNumberMetrics)
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100132 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200133 throw errors::InvalidArgument("MetricParams", "Too many.");
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100134 }
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000135
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200136 for (const LabeledMetricParameters& item : readingParams)
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000137 {
Krzysztof Grobelny62c08e92022-09-16 10:28:53 +0200138 utils::toOperationType(
139 utils::toUnderlying(item.at_label<ts::OperationType>()));
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000140 }
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000141}
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100142
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000143interfaces::Report& ReportManager::addReport(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100144 boost::asio::yield_context& yield, const std::string& reportId,
145 const std::string& reportName, const ReportingType reportingType,
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100146 const std::vector<ReportAction>& reportActions, Milliseconds interval,
147 const uint64_t appendLimit, const ReportUpdates reportUpdates,
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200148 ReadingParameters metricParams, const bool enabled)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000149{
Patrick Williams3a1c2972023-05-10 07:51:04 -0500150 auto labeledMetricParams = reportFactory->convertMetricParams(yield,
151 metricParams);
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000152
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100153 return addReport(reportId, reportName, reportingType, reportActions,
154 interval, appendLimit, reportUpdates,
Krzysztof Grobelny493e62e2022-02-14 10:55:50 +0100155 std::move(labeledMetricParams), enabled, Readings{});
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000156}
157
158interfaces::Report& ReportManager::addReport(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100159 const std::string& reportId, const std::string& reportName,
160 const ReportingType reportingType,
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100161 const std::vector<ReportAction>& reportActions, Milliseconds interval,
162 const uint64_t appendLimit, const ReportUpdates reportUpdates,
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200163 std::vector<LabeledMetricParameters> labeledMetricParams,
Krzysztof Grobelny493e62e2022-02-14 10:55:50 +0100164 const bool enabled, Readings readings)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000165{
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100166 const auto existingReportIds = utils::transform(
167 reports, [](const auto& report) { return report->getId(); });
168
Szymon Dompke32305f12022-07-05 15:37:21 +0200169 auto [id, name] = utils::makeIdName(reportId, reportName, reportNameDefault,
170 existingReportIds);
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100171
172 verifyAddReport(id, name, reportingType, interval, reportUpdates,
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +0000173 appendLimit, labeledMetricParams);
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000174
Krzysztof Grobelny493e62e2022-02-14 10:55:50 +0100175 reports.emplace_back(
176 reportFactory->make(id, name, reportingType, reportActions, interval,
177 appendLimit, reportUpdates, *this, *reportStorage,
178 labeledMetricParams, enabled, std::move(readings)));
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000179 return *reports.back();
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100180}
181
182void ReportManager::loadFromPersistent()
183{
184 std::vector<interfaces::JsonStorage::FilePath> paths =
185 reportStorage->list();
186
187 for (const auto& path : paths)
188 {
189 std::optional<nlohmann::json> data = reportStorage->load(path);
190 try
191 {
192 size_t version = data->at("Version").get<size_t>();
193 if (version != Report::reportVersion)
194 {
195 throw std::logic_error("Invalid version");
196 }
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100197 bool enabled = data->at("Enabled").get<bool>();
198 std::string& id = data->at("Id").get_ref<std::string&>();
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100199 std::string& name = data->at("Name").get_ref<std::string&>();
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100200
201 uint32_t reportingType = data->at("ReportingType").get<uint32_t>();
202 std::vector<ReportAction> reportActions = utils::transform(
203 data->at("ReportActions").get<std::vector<uint32_t>>(),
204 [](const auto reportAction) {
Patrick Williams3a1c2972023-05-10 07:51:04 -0500205 return utils::toReportAction(reportAction);
Patrick Williamsc7935fa2023-10-20 11:19:30 -0500206 });
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100207 uint64_t interval = data->at("Interval").get<uint64_t>();
Szymon Dompke3eb56862021-09-20 15:32:04 +0200208 uint64_t appendLimit = data->at("AppendLimit").get<uint64_t>();
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100209 uint32_t reportUpdates = data->at("ReportUpdates").get<uint32_t>();
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000210 auto readingParameters =
211 data->at("ReadingParameters")
212 .get<std::vector<LabeledMetricParameters>>();
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100213
Krzysztof Grobelny493e62e2022-02-14 10:55:50 +0100214 Readings readings = {};
215
216 if (auto it = data->find("MetricValues"); it != data->end())
217 {
218 const auto labeledReadings = it->get<LabeledReadings>();
219 readings = utils::toReadings(labeledReadings);
220 }
221
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100222 addReport(id, name, utils::toReportingType(reportingType),
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100223 reportActions, Milliseconds(interval), appendLimit,
224 utils::toReportUpdates(reportUpdates),
Krzysztof Grobelny493e62e2022-02-14 10:55:50 +0100225 std::move(readingParameters), enabled,
226 std::move(readings));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100227 }
228 catch (const std::exception& e)
229 {
230 phosphor::logging::log<phosphor::logging::level::ERR>(
231 "Failed to load report from storage",
232 phosphor::logging::entry(
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100233 "FILENAME=%s",
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100234 static_cast<std::filesystem::path>(path).c_str()),
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100235 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100236 reportStorage->remove(path);
237 }
238 }
239}