blob: c8103a6d2e5055bb1a2a809c5958411be7a4adfd [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 Grobelnyd2238192020-12-02 09:27:28 +00006#include "utils/transform.hpp"
Wludzik, Jozefe2362792020-10-27 17:23:55 +01007
8#include <phosphor-logging/log.hpp>
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +02009#include <sdbusplus/exception.hpp>
10
Wludzik, Jozefe2362792020-10-27 17:23:55 +010011#include <stdexcept>
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020012#include <system_error>
13
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000014ReadingParameters
15 convertToReadingParameters(ReadingParametersPastVersion params)
16{
17 return utils::transform(params, [](const auto& param) {
18 using namespace std::chrono_literals;
19
20 return ReadingParameters::value_type(
21 std::vector{{std::get<0>(param)}}, std::get<1>(param),
22 std::get<2>(param), std::get<3>(param),
23 utils::enumToString(CollectionTimeScope::point), 0u);
24 });
25}
26
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020027ReportManager::ReportManager(
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020028 std::unique_ptr<interfaces::ReportFactory> reportFactoryIn,
Wludzik, Jozefe2362792020-10-27 17:23:55 +010029 std::unique_ptr<interfaces::JsonStorage> reportStorageIn,
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020030 const std::shared_ptr<sdbusplus::asio::object_server>& objServerIn) :
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020031 reportFactory(std::move(reportFactoryIn)),
Wludzik, Jozefe2362792020-10-27 17:23:55 +010032 reportStorage(std::move(reportStorageIn)), objServer(objServerIn)
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020033{
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020034 reports.reserve(maxReports);
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010035
Wludzik, Jozefe2362792020-10-27 17:23:55 +010036 loadFromPersistent();
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020037
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020038 reportManagerIface = objServer->add_unique_interface(
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020039 reportManagerPath, reportManagerIfaceName, [this](auto& dbusIface) {
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020040 dbusIface.register_property_r(
Wludzik, Jozef503c1582020-12-11 14:48:01 +010041 "MaxReports", size_t{}, sdbusplus::vtable::property_::const_,
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020042 [](const auto&) { return maxReports; });
43 dbusIface.register_property_r(
Karol Niczyj32859b62021-05-19 10:20:46 +020044 "MaxReportNameLength", size_t{},
45 sdbusplus::vtable::property_::const_,
46 [](const auto&) { return maxReportNameLength; });
47 dbusIface.register_property_r(
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020048 "MinInterval", uint64_t{}, sdbusplus::vtable::property_::const_,
49 [](const auto&) -> uint64_t { return minInterval.count(); });
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020050
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020051 dbusIface.register_method(
Wludzik, Jozefe2362792020-10-27 17:23:55 +010052 "AddReport", [this](boost::asio::yield_context& yield,
53 const std::string& reportName,
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020054 const std::string& reportingType,
55 const bool emitsReadingsUpdate,
56 const bool logToMetricReportsCollection,
57 const uint64_t interval,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000058 ReadingParametersPastVersion metricParams) {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020059 constexpr auto enabledDefault = true;
Wludzik, Jozefe2362792020-10-27 17:23:55 +010060 return addReport(yield, reportName, reportingType,
61 emitsReadingsUpdate,
62 logToMetricReportsCollection,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000063 Milliseconds(interval),
64 convertToReadingParameters(
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020065 std::move(metricParams)),
66 enabledDefault)
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000067 .getPath();
68 });
69
70 dbusIface.register_method(
71 "AddReportFutureVersion",
72 [this](boost::asio::yield_context& yield,
73 const std::string& reportName,
74 const std::string& reportingType,
75 const bool emitsReadingsUpdate,
76 const bool logToMetricReportsCollection,
77 const uint64_t interval,
78 ReadingParameters metricParams) {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020079 constexpr auto enabledDefault = true;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000080 return addReport(yield, reportName, reportingType,
81 emitsReadingsUpdate,
82 logToMetricReportsCollection,
83 Milliseconds(interval),
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020084 std::move(metricParams), enabledDefault)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000085 .getPath();
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020086 });
87 });
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020088}
89
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020090void ReportManager::removeReport(const interfaces::Report* report)
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020091{
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020092 reports.erase(
93 std::remove_if(reports.begin(), reports.end(),
94 [report](const auto& x) { return report == x.get(); }),
95 reports.end());
Krzysztof Grobelny64b75a52020-09-18 10:17:16 +020096}
Wludzik, Jozefe2362792020-10-27 17:23:55 +010097
Karol Niczyj32859b62021-05-19 10:20:46 +020098void ReportManager::verifyReportNameLength(const std::string& reportName)
99{
100 if (reportName.length() > maxReportNameLength)
101 {
102 throw sdbusplus::exception::SdBusError(
103 static_cast<int>(std::errc::invalid_argument),
104 "Report name exceed maximum length");
105 }
106}
107
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000108void ReportManager::verifyAddReport(
109 const std::string& reportName, const std::string& reportingType,
110 Milliseconds interval,
111 const std::vector<LabeledMetricParameters>& readingParams)
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100112{
113 if (reports.size() >= maxReports)
114 {
115 throw sdbusplus::exception::SdBusError(
116 static_cast<int>(std::errc::too_many_files_open),
117 "Reached maximal report count");
118 }
119
Karol Niczyj32859b62021-05-19 10:20:46 +0200120 verifyReportNameLength(reportName);
121
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100122 for (const auto& report : reports)
123 {
124 if (report->getName() == reportName)
125 {
126 throw sdbusplus::exception::SdBusError(
127 static_cast<int>(std::errc::file_exists), "Duplicate report");
128 }
129 }
130
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100131 auto found = std::find(supportedReportingType.begin(),
132 supportedReportingType.end(), reportingType);
133 if (found == supportedReportingType.end())
134 {
135 throw sdbusplus::exception::SdBusError(
136 static_cast<int>(std::errc::invalid_argument),
137 "Invalid reportingType");
138 }
139
140 if (reportingType == "Periodic" && interval < minInterval)
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100141 {
142 throw sdbusplus::exception::SdBusError(
143 static_cast<int>(std::errc::invalid_argument), "Invalid interval");
144 }
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100145
Wludzik, Jozef503c1582020-12-11 14:48:01 +0100146 if (readingParams.size() > maxReadingParams)
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000147
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100148 {
149 throw sdbusplus::exception::SdBusError(
150 static_cast<int>(std::errc::argument_list_too_long),
151 "Too many reading parameters");
152 }
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000153
154 try
155 {
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000156 namespace ts = utils::tstring;
157
158 for (const LabeledMetricParameters& item : readingParams)
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000159 {
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000160 utils::toOperationType(
161 utils::toUnderlying(item.at_label<ts::OperationType>()));
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000162 }
163 }
164 catch (const std::exception& e)
165 {
166 throw sdbusplus::exception::SdBusError(
167 static_cast<int>(std::errc::invalid_argument), e.what());
168 }
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000169}
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100170
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000171interfaces::Report& ReportManager::addReport(
172 boost::asio::yield_context& yield, const std::string& reportName,
173 const std::string& reportingType, const bool emitsReadingsUpdate,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000174 const bool logToMetricReportsCollection, Milliseconds interval,
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200175 ReadingParameters metricParams, const bool enabled)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000176{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000177 auto labeledMetricParams =
178 reportFactory->convertMetricParams(yield, metricParams);
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000179
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000180 return addReport(reportName, reportingType, emitsReadingsUpdate,
181 logToMetricReportsCollection, interval,
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200182 std::move(labeledMetricParams), enabled);
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000183}
184
185interfaces::Report& ReportManager::addReport(
186 const std::string& reportName, const std::string& reportingType,
187 const bool emitsReadingsUpdate, const bool logToMetricReportsCollection,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000188 Milliseconds interval,
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200189 std::vector<LabeledMetricParameters> labeledMetricParams,
190 const bool enabled)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000191{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000192 verifyAddReport(reportName, reportingType, interval, labeledMetricParams);
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000193
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000194 reports.emplace_back(
195 reportFactory->make(reportName, reportingType, emitsReadingsUpdate,
196 logToMetricReportsCollection, interval, *this,
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200197 *reportStorage, labeledMetricParams, enabled));
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000198 return *reports.back();
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100199}
200
201void ReportManager::loadFromPersistent()
202{
203 std::vector<interfaces::JsonStorage::FilePath> paths =
204 reportStorage->list();
205
206 for (const auto& path : paths)
207 {
208 std::optional<nlohmann::json> data = reportStorage->load(path);
209 try
210 {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200211 bool enabled = data->at("Enabled").get<bool>();
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100212 size_t version = data->at("Version").get<size_t>();
213 if (version != Report::reportVersion)
214 {
215 throw std::logic_error("Invalid version");
216 }
217 std::string& name = data->at("Name").get_ref<std::string&>();
218 std::string& reportingType =
219 data->at("ReportingType").get_ref<std::string&>();
220 bool emitsReadingsSignal =
221 data->at("EmitsReadingsUpdate").get<bool>();
222 bool logToMetricReportsCollection =
223 data->at("LogToMetricReportsCollection").get<bool>();
224 uint64_t interval = data->at("Interval").get<uint64_t>();
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000225 auto readingParameters =
226 data->at("ReadingParameters")
227 .get<std::vector<LabeledMetricParameters>>();
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100228
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000229 addReport(name, reportingType, emitsReadingsSignal,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000230 logToMetricReportsCollection, Milliseconds(interval),
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200231 std::move(readingParameters), enabled);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100232 }
233 catch (const std::exception& e)
234 {
235 phosphor::logging::log<phosphor::logging::level::ERR>(
236 "Failed to load report from storage",
237 phosphor::logging::entry(
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100238 "FILENAME=%s",
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100239 static_cast<std::filesystem::path>(path).c_str()),
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100240 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100241 reportStorage->remove(path);
242 }
243 }
244}
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100245
246void ReportManager::updateReport(const std::string& name)
247{
248 for (auto& report : reports)
249 {
250 if (report->getName() == name)
251 {
252 report->updateReadings();
253 return;
254 }
255 }
256}