blob: 9b7b9ef5246f090e6dcf67192cd272dc944375b3 [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"
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +01006#include "utils/generate_id.hpp"
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +00007#include "utils/transform.hpp"
Wludzik, Jozefe2362792020-10-27 17:23:55 +01008
9#include <phosphor-logging/log.hpp>
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020010#include <sdbusplus/exception.hpp>
11
Wludzik, Jozefe2362792020-10-27 17:23:55 +010012#include <stdexcept>
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020013#include <system_error>
14
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000015ReadingParameters
16 convertToReadingParameters(ReadingParametersPastVersion params)
17{
18 return utils::transform(params, [](const auto& param) {
19 using namespace std::chrono_literals;
20
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010021 const auto& [sensorPath, operationType, id, metadata] = param;
22
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000023 return ReadingParameters::value_type(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010024 std::vector<
25 std::tuple<sdbusplus::message::object_path, std::string>>{
26 {sensorPath, metadata}},
27 operationType, id, utils::enumToString(CollectionTimeScope::point),
28 0u);
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000029 });
30}
31
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020032ReportManager::ReportManager(
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020033 std::unique_ptr<interfaces::ReportFactory> reportFactoryIn,
Wludzik, Jozefe2362792020-10-27 17:23:55 +010034 std::unique_ptr<interfaces::JsonStorage> reportStorageIn,
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010035 const std::shared_ptr<sdbusplus::asio::object_server>& objServerIn,
36 std::unique_ptr<interfaces::TriggerManager>& triggerManagerIn) :
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020037 reportFactory(std::move(reportFactoryIn)),
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010038 reportStorage(std::move(reportStorageIn)), objServer(objServerIn),
39 triggerManager(triggerManagerIn)
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020040{
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020041 reports.reserve(maxReports);
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010042
Wludzik, Jozefe2362792020-10-27 17:23:55 +010043 loadFromPersistent();
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020044
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020045 reportManagerIface = objServer->add_unique_interface(
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020046 reportManagerPath, reportManagerIfaceName, [this](auto& dbusIface) {
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020047 dbusIface.register_property_r(
Wludzik, Jozef503c1582020-12-11 14:48:01 +010048 "MaxReports", size_t{}, sdbusplus::vtable::property_::const_,
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020049 [](const auto&) { return maxReports; });
50 dbusIface.register_property_r(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010051 "MaxReportIdLength", size_t{},
Karol Niczyj32859b62021-05-19 10:20:46 +020052 sdbusplus::vtable::property_::const_,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010053 [](const auto&) { return maxReportIdLength; });
Karol Niczyj32859b62021-05-19 10:20:46 +020054 dbusIface.register_property_r(
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020055 "MinInterval", uint64_t{}, sdbusplus::vtable::property_::const_,
56 [](const auto&) -> uint64_t { return minInterval.count(); });
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020057
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020058 dbusIface.register_method(
Wludzik, Jozefe2362792020-10-27 17:23:55 +010059 "AddReport", [this](boost::asio::yield_context& yield,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010060 const std::string& reportId,
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020061 const std::string& reportingType,
62 const bool emitsReadingsUpdate,
63 const bool logToMetricReportsCollection,
64 const uint64_t interval,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000065 ReadingParametersPastVersion metricParams) {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020066 constexpr auto enabledDefault = true;
Szymon Dompke3eb56862021-09-20 15:32:04 +020067 constexpr uint64_t appendLimitDefault = 0;
68 constexpr ReportUpdates reportUpdatesDefault =
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010069 ReportUpdates::overwrite;
70
71 std::vector<ReportAction> reportActions;
72
73 if (emitsReadingsUpdate)
74 {
75 reportActions.emplace_back(
76 ReportAction::emitsReadingsUpdate);
77 }
78 if (logToMetricReportsCollection)
79 {
80 reportActions.emplace_back(
81 ReportAction::logToMetricReportsCollection);
82 }
83
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010084 return addReport(yield, reportId, reportId,
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010085 utils::toReportingType(reportingType),
86 reportActions, Milliseconds(interval),
87 appendLimitDefault, reportUpdatesDefault,
88 convertToReadingParameters(
89 std::move(metricParams)),
90 enabledDefault)
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000091 .getPath();
92 });
93
94 dbusIface.register_method(
95 "AddReportFutureVersion",
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010096 [this](
97 boost::asio::yield_context& yield,
98 const std::string& reportId, const std::string& reportName,
99 const std::string& reportingType,
100 const std::string& reportUpdates,
101 const uint64_t appendLimit,
102 const std::vector<std::string>& reportActions,
103 const uint64_t interval, ReadingParameters metricParams) {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200104 constexpr auto enabledDefault = true;
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100105 return addReport(yield, reportId, reportName,
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100106 utils::toReportingType(reportingType),
107 utils::transform(
108 reportActions,
109 [](const auto& reportAction) {
110 return utils::toReportAction(
111 reportAction);
112 }),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200113 Milliseconds(interval), appendLimit,
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100114 utils::toReportUpdates(reportUpdates),
115 std::move(metricParams), enabledDefault)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000116 .getPath();
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +0200117 });
118 });
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +0200119}
120
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200121void ReportManager::removeReport(const interfaces::Report* report)
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +0200122{
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +0200123 reports.erase(
124 std::remove_if(reports.begin(), reports.end(),
125 [report](const auto& x) { return report == x.get(); }),
126 reports.end());
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +0200127}
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100128
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000129void ReportManager::verifyAddReport(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100130 const std::string& reportId, const std::string& reportName,
131 const ReportingType reportingType, Milliseconds interval,
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +0000132 const ReportUpdates reportUpdates, const uint64_t appendLimit,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000133 const std::vector<LabeledMetricParameters>& readingParams)
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100134{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100135 if (reportingType == ReportingType::onChange)
136 {
137 throw sdbusplus::exception::SdBusError(
138 static_cast<int>(std::errc::invalid_argument),
139 "Invalid reportingType");
140 }
141
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100142 if (reports.size() >= maxReports)
143 {
144 throw sdbusplus::exception::SdBusError(
145 static_cast<int>(std::errc::too_many_files_open),
146 "Reached maximal report count");
147 }
148
Krzysztof Grobelnye6c417c2022-02-02 17:25:53 +0100149 if (appendLimit > maxAppendLimit &&
150 appendLimit != std::numeric_limits<uint64_t>::max())
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +0000151 {
152 throw sdbusplus::exception::SdBusError(
153 static_cast<int>(std::errc::invalid_argument),
154 "Append limit out of range");
155 }
156
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100157 if (reportingType == ReportingType::periodic && interval < minInterval)
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100158 {
159 throw sdbusplus::exception::SdBusError(
160 static_cast<int>(std::errc::invalid_argument), "Invalid interval");
161 }
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100162
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +0000163 size_t metricCount = 0;
164 for (auto metricParam : readingParams)
165 {
166 auto metricParamsVec =
167 metricParam.at_label<utils::tstring::SensorPath>();
168 metricCount += metricParamsVec.size();
169 }
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000170
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +0000171 if (readingParams.size() > maxNumberMetrics ||
172 metricCount > maxNumberMetrics)
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100173 {
174 throw sdbusplus::exception::SdBusError(
175 static_cast<int>(std::errc::argument_list_too_long),
176 "Too many reading parameters");
177 }
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000178
179 try
180 {
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000181 namespace ts = utils::tstring;
182
183 for (const LabeledMetricParameters& item : readingParams)
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000184 {
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000185 utils::toOperationType(
186 utils::toUnderlying(item.at_label<ts::OperationType>()));
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000187 }
188 }
189 catch (const std::exception& e)
190 {
191 throw sdbusplus::exception::SdBusError(
192 static_cast<int>(std::errc::invalid_argument), e.what());
193 }
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000194}
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100195
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000196interfaces::Report& ReportManager::addReport(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100197 boost::asio::yield_context& yield, const std::string& reportId,
198 const std::string& reportName, const ReportingType reportingType,
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100199 const std::vector<ReportAction>& reportActions, Milliseconds interval,
200 const uint64_t appendLimit, const ReportUpdates reportUpdates,
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200201 ReadingParameters metricParams, const bool enabled)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000202{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000203 auto labeledMetricParams =
204 reportFactory->convertMetricParams(yield, metricParams);
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000205
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100206 return addReport(reportId, reportName, reportingType, reportActions,
207 interval, appendLimit, reportUpdates,
208 std::move(labeledMetricParams), enabled);
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000209}
210
211interfaces::Report& ReportManager::addReport(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100212 const std::string& reportId, const std::string& reportName,
213 const ReportingType reportingType,
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100214 const std::vector<ReportAction>& reportActions, Milliseconds interval,
215 const uint64_t appendLimit, const ReportUpdates reportUpdates,
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200216 std::vector<LabeledMetricParameters> labeledMetricParams,
217 const bool enabled)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000218{
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100219 const auto existingReportIds = utils::transform(
220 reports, [](const auto& report) { return report->getId(); });
221
Krzysztof Grobelnya950e422021-12-31 13:49:00 +0100222 auto [id, name] = utils::generateId(reportId, reportName, reportNameDefault,
223 existingReportIds, maxReportIdLength);
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100224
225 verifyAddReport(id, name, reportingType, interval, reportUpdates,
Ankita Vilas Gawadecd5b0b72022-01-20 20:55:04 +0000226 appendLimit, labeledMetricParams);
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000227
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100228 std::vector<std::string> triggerIds;
229 if (triggerManager)
230 {
231 triggerIds = triggerManager->getTriggerIdsForReport(id);
232 }
233
234 reports.emplace_back(
235 reportFactory->make(id, name, reportingType, reportActions, interval,
236 appendLimit, reportUpdates, *this, *reportStorage,
237 labeledMetricParams, enabled, triggerIds));
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000238 return *reports.back();
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100239}
240
241void ReportManager::loadFromPersistent()
242{
243 std::vector<interfaces::JsonStorage::FilePath> paths =
244 reportStorage->list();
245
246 for (const auto& path : paths)
247 {
248 std::optional<nlohmann::json> data = reportStorage->load(path);
249 try
250 {
251 size_t version = data->at("Version").get<size_t>();
252 if (version != Report::reportVersion)
253 {
254 throw std::logic_error("Invalid version");
255 }
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100256 bool enabled = data->at("Enabled").get<bool>();
257 std::string& id = data->at("Id").get_ref<std::string&>();
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100258 std::string& name = data->at("Name").get_ref<std::string&>();
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100259
260 uint32_t reportingType = data->at("ReportingType").get<uint32_t>();
261 std::vector<ReportAction> reportActions = utils::transform(
262 data->at("ReportActions").get<std::vector<uint32_t>>(),
263 [](const auto reportAction) {
264 return utils::toReportAction(reportAction);
265 });
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100266 uint64_t interval = data->at("Interval").get<uint64_t>();
Szymon Dompke3eb56862021-09-20 15:32:04 +0200267 uint64_t appendLimit = data->at("AppendLimit").get<uint64_t>();
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100268 uint32_t reportUpdates = data->at("ReportUpdates").get<uint32_t>();
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000269 auto readingParameters =
270 data->at("ReadingParameters")
271 .get<std::vector<LabeledMetricParameters>>();
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100272
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100273 addReport(id, name, utils::toReportingType(reportingType),
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100274 reportActions, Milliseconds(interval), appendLimit,
275 utils::toReportUpdates(reportUpdates),
276 std::move(readingParameters), enabled);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100277 }
278 catch (const std::exception& e)
279 {
280 phosphor::logging::log<phosphor::logging::level::ERR>(
281 "Failed to load report from storage",
282 phosphor::logging::entry(
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100283 "FILENAME=%s",
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100284 static_cast<std::filesystem::path>(path).c_str()),
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100285 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100286 reportStorage->remove(path);
287 }
288 }
289}
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100290
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100291void ReportManager::updateReport(const std::string& id)
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100292{
293 for (auto& report : reports)
294 {
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100295 if (report->getId() == id)
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100296 {
297 report->updateReadings();
298 return;
299 }
300 }
301}
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100302
303void ReportManager::updateTriggerIds(const std::string& reportId,
304 const std::string& triggerId,
305 TriggerIdUpdate updateType)
306{
307 if (auto res = std::find_if(reports.begin(), reports.end(),
308 [&reportId](const auto& report) {
309 return report->getId() == reportId;
310 });
311 res != reports.end())
312 {
313 (*res)->updateTriggerIds(triggerId, updateType);
314 }
315}