xref: /openbmc/telemetry/src/trigger_factory.cpp (revision 4416fce6fb6539b4e2a6a94a8248934c2eb29820)
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, bool isDiscrete, bool logToJournal,
25     bool logToRedfish, bool updateReport,
26     const std::vector<std::string>& reportNames,
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<std::shared_ptr<interfaces::Threshold>> thresholds;
34 
35     if (isDiscrete)
36     {
37         const auto& labeledDiscreteThresholdParams =
38             std::get<std::vector<discrete::LabeledThresholdParam>>(
39                 labeledThresholdParams);
40         for (const auto& labeledThresholdParam : labeledDiscreteThresholdParams)
41         {
42             std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
43 
44             std::string thresholdName =
45                 labeledThresholdParam.at_label<ts::UserId>();
46             discrete::Severity severity =
47                 labeledThresholdParam.at_label<ts::Severity>();
48             std::chrono::milliseconds dwellTime = std::chrono::milliseconds(
49                 labeledThresholdParam.at_label<ts::DwellTime>());
50             double thresholdValue =
51                 labeledThresholdParam.at_label<ts::ThresholdValue>();
52 
53             if (logToJournal)
54             {
55                 actions.emplace_back(
56                     std::make_unique<action::discrete::LogToJournal>(severity));
57             }
58             if (logToRedfish)
59             {
60                 actions.emplace_back(
61                     std::make_unique<action::discrete::LogToRedfish>(severity));
62             }
63             if (updateReport)
64             {
65                 actions.emplace_back(std::make_unique<action::UpdateReport>(
66                     reportManager, reportNames));
67             }
68 
69             thresholds.emplace_back(std::make_shared<DiscreteThreshold>(
70                 bus->get_io_context(), sensors, sensorNames, std::move(actions),
71                 std::chrono::milliseconds(dwellTime), thresholdValue,
72                 thresholdName));
73         }
74         if (labeledDiscreteThresholdParams.empty())
75         {
76             std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
77             if (logToJournal)
78             {
79                 actions.emplace_back(
80                     std::make_unique<
81                         action::discrete::onChange::LogToJournal>());
82             }
83             if (logToRedfish)
84             {
85                 actions.emplace_back(
86                     std::make_unique<
87                         action::discrete::onChange::LogToRedfish>());
88             }
89             if (updateReport)
90             {
91                 actions.emplace_back(std::make_unique<action::UpdateReport>(
92                     reportManager, reportNames));
93             }
94 
95             thresholds.emplace_back(std::make_shared<OnChangeThreshold>(
96                 sensors, sensorNames, std::move(actions)));
97         }
98     }
99     else
100     {
101         const auto& labeledNumericThresholdParams =
102             std::get<std::vector<numeric::LabeledThresholdParam>>(
103                 labeledThresholdParams);
104 
105         for (const auto& labeledThresholdParam : labeledNumericThresholdParams)
106         {
107             std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
108             auto type = labeledThresholdParam.at_label<ts::Type>();
109             auto dwellTime = std::chrono::milliseconds(
110                 labeledThresholdParam.at_label<ts::DwellTime>());
111             auto direction = labeledThresholdParam.at_label<ts::Direction>();
112             auto thresholdValue =
113                 double{labeledThresholdParam.at_label<ts::ThresholdValue>()};
114 
115             if (logToJournal)
116             {
117                 actions.emplace_back(
118                     std::make_unique<action::numeric::LogToJournal>(
119                         type, thresholdValue));
120             }
121 
122             if (logToRedfish)
123             {
124                 actions.emplace_back(
125                     std::make_unique<action::numeric::LogToRedfish>(
126                         type, thresholdValue));
127             }
128 
129             if (updateReport)
130             {
131                 actions.emplace_back(std::make_unique<action::UpdateReport>(
132                     reportManager, reportNames));
133             }
134 
135             thresholds.emplace_back(std::make_shared<NumericThreshold>(
136                 bus->get_io_context(), sensors, sensorNames, std::move(actions),
137                 dwellTime, direction, thresholdValue));
138         }
139     }
140 
141     return std::make_unique<Trigger>(
142         bus->get_io_context(), objServer, name, isDiscrete, logToJournal,
143         logToRedfish, updateReport, reportNames, labeledSensorsInfo,
144         labeledThresholdParams, std::move(thresholds), triggerManager,
145         triggerStorage);
146 }
147 
148 std::pair<std::vector<std::shared_ptr<interfaces::Sensor>>,
149           std::vector<std::string>>
150     TriggerFactory::getSensors(
151         const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
152 {
153     std::vector<std::shared_ptr<interfaces::Sensor>> sensors;
154     std::vector<std::string> sensorNames;
155 
156     for (const auto& labeledSensorInfo : labeledSensorsInfo)
157     {
158         const auto& service = labeledSensorInfo.at_label<ts::Service>();
159         const auto& sensorPath = labeledSensorInfo.at_label<ts::SensorPath>();
160         const auto& metadata = labeledSensorInfo.at_label<ts::SensorMetadata>();
161 
162         sensors.emplace_back(sensorCache.makeSensor<Sensor>(
163             service, sensorPath, bus->get_io_context(), bus));
164 
165         if (metadata.empty())
166         {
167             sensorNames.emplace_back(sensorPath);
168         }
169         else
170         {
171             sensorNames.emplace_back(metadata);
172         }
173     }
174 
175     return {sensors, sensorNames};
176 }
177 
178 std::vector<LabeledSensorInfo>
179     TriggerFactory::getLabeledSensorsInfo(boost::asio::yield_context& yield,
180                                           const SensorsInfo& sensorsInfo) const
181 {
182     auto tree = utils::getSubTreeSensors(yield, bus);
183 
184     return utils::transform(sensorsInfo, [&tree](const auto& item) {
185         const auto& [sensorPath, metadata] = item;
186         auto found = std::find_if(
187             tree.begin(), tree.end(),
188             [&sensorPath](const auto& x) { return x.first == sensorPath; });
189 
190         if (tree.end() != found)
191         {
192             const auto& [service, ifaces] = found->second.front();
193             return LabeledSensorInfo(service, sensorPath, metadata);
194         }
195         throw std::runtime_error("Not found");
196     });
197 }
198