blob: c7982476fe23d7c32cb7268365ab89ad60dc47f1 [file] [log] [blame]
#include "report_factory.hpp"
#include "metric.hpp"
#include "report.hpp"
#include "sensor.hpp"
#include "utils/clock.hpp"
#include "utils/conversion.hpp"
#include "utils/dbus_mapper.hpp"
#include "utils/transform.hpp"
ReportFactory::ReportFactory(
std::shared_ptr<sdbusplus::asio::connection> bus,
const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
SensorCache& sensorCache) :
bus(std::move(bus)), objServer(objServer), sensorCache(sensorCache)
{}
std::unique_ptr<interfaces::Report> ReportFactory::make(
const std::string& id, const std::string& name,
const ReportingType reportingType,
const std::vector<ReportAction>& reportActions, Milliseconds period,
uint64_t appendLimit, const ReportUpdates reportUpdates,
interfaces::ReportManager& reportManager,
interfaces::JsonStorage& reportStorage,
std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
Readings readings) const
{
auto metrics = utils::transform(labeledMetricParams,
[this](const LabeledMetricParameters& param)
-> std::shared_ptr<interfaces::Metric> {
namespace ts = utils::tstring;
return std::make_shared<Metric>(
getSensors(param.at_label<ts::SensorPath>()),
param.at_label<ts::OperationType>(),
param.at_label<ts::CollectionTimeScope>(),
param.at_label<ts::CollectionDuration>(),
std::make_unique<Clock>());
});
return std::make_unique<Report>(
bus->get_io_context(), objServer, id, name, reportingType,
reportActions, period, appendLimit, reportUpdates, reportManager,
reportStorage, std::move(metrics), *this, enabled,
std::make_unique<Clock>(), std::move(readings));
}
void ReportFactory::updateMetrics(
std::vector<std::shared_ptr<interfaces::Metric>>& metrics, bool enabled,
const std::vector<LabeledMetricParameters>& labeledMetricParams) const
{
std::vector<std::shared_ptr<interfaces::Metric>> oldMetrics = metrics;
std::vector<std::shared_ptr<interfaces::Metric>> newMetrics;
for (const auto& labeledMetricParam : labeledMetricParams)
{
auto existing = std::find_if(oldMetrics.begin(), oldMetrics.end(),
[labeledMetricParam](auto metric) {
return labeledMetricParam == metric->dumpConfiguration();
});
if (existing != oldMetrics.end())
{
newMetrics.emplace_back(*existing);
oldMetrics.erase(existing);
continue;
}
namespace ts = utils::tstring;
newMetrics.emplace_back(std::make_shared<Metric>(
getSensors(labeledMetricParam.at_label<ts::SensorPath>()),
labeledMetricParam.at_label<ts::OperationType>(),
labeledMetricParam.at_label<ts::CollectionTimeScope>(),
labeledMetricParam.at_label<ts::CollectionDuration>(),
std::make_unique<Clock>()));
if (enabled)
{
newMetrics.back()->initialize();
}
}
if (enabled)
{
for (auto& metric : oldMetrics)
{
metric->deinitialize();
}
}
metrics = std::move(newMetrics);
}
Sensors ReportFactory::getSensors(
const std::vector<LabeledSensorInfo>& sensorPaths) const
{
using namespace utils::tstring;
return utils::transform(sensorPaths,
[this](const LabeledSensorInfo& sensorPath)
-> std::shared_ptr<interfaces::Sensor> {
return sensorCache.makeSensor<Sensor>(
sensorPath.at_label<Service>(), sensorPath.at_label<Path>(),
sensorPath.at_label<Metadata>(), bus->get_io_context(), bus);
});
}
std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
boost::asio::yield_context& yield,
const ReadingParameters& metricParams) const
{
if (metricParams.empty())
{
return {};
}
auto tree = utils::getSubTreeSensors(yield, bus);
return getMetricParamsFromSensorTree(metricParams, tree);
}
std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
const ReadingParameters& metricParams) const
{
if (metricParams.empty())
{
return {};
}
auto tree = utils::getSubTreeSensors(bus);
return getMetricParamsFromSensorTree(metricParams, tree);
}
std::vector<LabeledMetricParameters>
ReportFactory::getMetricParamsFromSensorTree(
const ReadingParameters& metricParams,
const std::vector<utils::SensorTree>& tree) const
{
try
{
return utils::transform(metricParams, [&tree](const auto& item) {
auto [sensorPaths, operationType, collectionTimeScope,
collectionDuration] = item;
std::vector<LabeledSensorInfo> sensorParameters;
for (const auto& [sensorPath, metadata] : sensorPaths)
{
auto it = std::find_if(tree.begin(), tree.end(),
[path = sensorPath](const auto& v) {
return v.first == path;
});
if (it != tree.end() && it->second.size() == 1)
{
const auto& [service, ifaces] = it->second.front();
sensorParameters.emplace_back(service, sensorPath,
metadata);
}
}
if (sensorParameters.size() != sensorPaths.size())
{
throw errors::InvalidArgument("ReadingParameters",
"Service not found.");
}
if (operationType.empty())
{
operationType = utils::enumToString(OperationType::avg);
}
else if (operationType == "SINGLE")
{
operationType = utils::enumToString(OperationType::avg);
collectionTimeScope =
utils::enumToString(CollectionTimeScope::point);
}
if (collectionTimeScope.empty())
{
collectionTimeScope =
utils::enumToString(CollectionTimeScope::point);
}
return LabeledMetricParameters(
std::move(sensorParameters),
utils::toOperationType(operationType),
utils::toCollectionTimeScope(collectionTimeScope),
CollectionDuration(Milliseconds(collectionDuration)));
});
}
catch (const errors::InvalidArgument& e)
{
if (e.propertyName == "ReadingParameters")
{
throw;
}
using namespace std::literals::string_literals;
throw errors::InvalidArgument("ReadingParameters."s + e.propertyName);
}
}