xref: /openbmc/telemetry/src/trigger_factory.cpp (revision 2001301a0f2ce71797cf171305a1d0eb0d288fe6)
1 #include "trigger_factory.hpp"
2 
3 #include "discrete_threshold.hpp"
4 #include "numeric_threshold.hpp"
5 #include "on_change_threshold.hpp"
6 #include "sensor.hpp"
7 #include "trigger.hpp"
8 #include "trigger_actions.hpp"
9 #include "utils/dbus_mapper.hpp"
10 #include "utils/transform.hpp"
11 
12 namespace ts = utils::tstring;
13 
14 TriggerFactory::TriggerFactory(
15     std::shared_ptr<sdbusplus::asio::connection> bus,
16     std::shared_ptr<sdbusplus::asio::object_server> objServer,
17     SensorCache& sensorCache, interfaces::ReportManager& reportManager) :
18     bus(std::move(bus)),
19     objServer(std::move(objServer)), sensorCache(sensorCache),
20     reportManager(reportManager)
21 {}
22 
23 std::unique_ptr<interfaces::Trigger> TriggerFactory::make(
24     const std::string& name, const std::vector<std::string>& triggerActionsIn,
25     const std::vector<std::string>& reportNames,
26     interfaces::TriggerManager& triggerManager,
27     interfaces::JsonStorage& triggerStorage,
28     const LabeledTriggerThresholdParams& labeledThresholdParams,
29     const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
30 {
31     const auto& [sensors, sensorNames] = getSensors(labeledSensorsInfo);
32     std::vector<TriggerAction> triggerActions;
33     std::transform(triggerActionsIn.begin(), triggerActionsIn.end(),
34                    std::back_inserter(triggerActions),
35                    [](auto& triggerActionStr) {
36                        return stringToTriggerAction(triggerActionStr);
37                    });
38     std::vector<std::shared_ptr<interfaces::Threshold>> thresholds;
39 
40     if (isTriggerThresholdDiscrete(labeledThresholdParams))
41     {
42         const auto& labeledDiscreteThresholdParams =
43             std::get<std::vector<discrete::LabeledThresholdParam>>(
44                 labeledThresholdParams);
45         for (const auto& labeledThresholdParam : labeledDiscreteThresholdParams)
46         {
47             std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
48 
49             std::string thresholdName =
50                 labeledThresholdParam.at_label<ts::UserId>();
51             discrete::Severity severity =
52                 labeledThresholdParam.at_label<ts::Severity>();
53             auto dwellTime =
54                 Milliseconds(labeledThresholdParam.at_label<ts::DwellTime>());
55             std::string thresholdValue =
56                 labeledThresholdParam.at_label<ts::ThresholdValue>();
57 
58             action::discrete::fillActions(actions, triggerActions, severity,
59                                           reportManager, reportNames);
60 
61             thresholds.emplace_back(std::make_shared<DiscreteThreshold>(
62                 bus->get_io_context(), sensors, sensorNames, std::move(actions),
63                 Milliseconds(dwellTime), std::stod(thresholdValue),
64                 thresholdName));
65         }
66         if (labeledDiscreteThresholdParams.empty())
67         {
68             std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
69             action::discrete::onChange::fillActions(actions, triggerActions,
70                                                     reportManager, reportNames);
71 
72             thresholds.emplace_back(std::make_shared<OnChangeThreshold>(
73                 sensors, sensorNames, std::move(actions)));
74         }
75     }
76     else
77     {
78         const auto& labeledNumericThresholdParams =
79             std::get<std::vector<numeric::LabeledThresholdParam>>(
80                 labeledThresholdParams);
81 
82         for (const auto& labeledThresholdParam : labeledNumericThresholdParams)
83         {
84             std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
85             auto type = labeledThresholdParam.at_label<ts::Type>();
86             auto dwellTime =
87                 Milliseconds(labeledThresholdParam.at_label<ts::DwellTime>());
88             auto direction = labeledThresholdParam.at_label<ts::Direction>();
89             auto thresholdValue =
90                 double{labeledThresholdParam.at_label<ts::ThresholdValue>()};
91 
92             action::numeric::fillActions(actions, triggerActions, type,
93                                          thresholdValue, reportManager,
94                                          reportNames);
95 
96             thresholds.emplace_back(std::make_shared<NumericThreshold>(
97                 bus->get_io_context(), sensors, sensorNames, std::move(actions),
98                 dwellTime, direction, thresholdValue));
99         }
100     }
101 
102     return std::make_unique<Trigger>(
103         bus->get_io_context(), objServer, name, triggerActionsIn, reportNames,
104         labeledSensorsInfo, labeledThresholdParams, std::move(thresholds),
105         triggerManager, triggerStorage);
106 }
107 
108 std::pair<Sensors, std::vector<std::string>> TriggerFactory::getSensors(
109     const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
110 {
111     Sensors sensors;
112     std::vector<std::string> sensorNames;
113 
114     for (const auto& labeledSensorInfo : labeledSensorsInfo)
115     {
116         const auto& service = labeledSensorInfo.at_label<ts::Service>();
117         const auto& sensorPath = labeledSensorInfo.at_label<ts::SensorPath>();
118         const auto& metadata = labeledSensorInfo.at_label<ts::SensorMetadata>();
119 
120         sensors.emplace_back(sensorCache.makeSensor<Sensor>(
121             service, sensorPath, bus->get_io_context(), bus));
122 
123         if (metadata.empty())
124         {
125             sensorNames.emplace_back(sensorPath);
126         }
127         else
128         {
129             sensorNames.emplace_back(metadata);
130         }
131     }
132 
133     return {sensors, sensorNames};
134 }
135 
136 std::vector<LabeledSensorInfo>
137     TriggerFactory::getLabeledSensorsInfo(boost::asio::yield_context& yield,
138                                           const SensorsInfo& sensorsInfo) const
139 {
140     auto tree = utils::getSubTreeSensors(yield, bus);
141 
142     return utils::transform(sensorsInfo, [&tree](const auto& item) {
143         const auto& [sensorPath, metadata] = item;
144         auto found = std::find_if(
145             tree.begin(), tree.end(),
146             [&sensorPath](const auto& x) { return x.first == sensorPath; });
147 
148         if (tree.end() != found)
149         {
150             const auto& [service, ifaces] = found->second.front();
151             return LabeledSensorInfo(service, sensorPath, metadata);
152         }
153         throw std::runtime_error("Not found");
154     });
155 }
156