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