xref: /openbmc/telemetry/src/trigger_factory.cpp (revision a4e6761643f2ff306d6928ea5537eb151fae79a0)
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 
11 TriggerFactory::TriggerFactory(
12     std::shared_ptr<sdbusplus::asio::connection> bus,
13     std::shared_ptr<sdbusplus::asio::object_server> objServer,
14     SensorCache& sensorCache, interfaces::ReportManager& reportManager) :
15     bus(std::move(bus)),
16     objServer(std::move(objServer)), sensorCache(sensorCache),
17     reportManager(reportManager)
18 {}
19 
20 std::unique_ptr<interfaces::Trigger>
21     TriggerFactory::make(boost::asio::yield_context& yield,
22                          const std::string& name, bool isDiscrete,
23                          bool logToJournal, bool logToRedfish,
24                          bool updateReport, const TriggerSensors& sensorPaths,
25                          const std::vector<std::string>& reportNames,
26                          const TriggerThresholdParams& thresholdParams,
27                          interfaces::TriggerManager& triggerManager,
28                          interfaces::JsonStorage& triggerStorage) const
29 {
30     auto [sensors, sensorNames] = getSensors(yield, sensorPaths);
31     std::vector<std::shared_ptr<interfaces::Threshold>> thresholds;
32 
33     if (isDiscrete)
34     {
35         const auto& params =
36             std::get<std::vector<discrete::ThresholdParam>>(thresholdParams);
37         for (const auto& [thresholdName, severityStr, dwellTime,
38                           thresholdValue] : params)
39         {
40             discrete::Severity severity =
41                 discrete::stringToSeverity(severityStr);
42             std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
43             if (logToJournal)
44             {
45                 actions.emplace_back(
46                     std::make_unique<action::discrete::LogToJournal>(severity));
47             }
48             if (logToRedfish)
49             {
50                 actions.emplace_back(
51                     std::make_unique<action::discrete::LogToRedfish>(severity));
52             }
53             if (updateReport)
54             {
55                 actions.emplace_back(std::make_unique<action::UpdateReport>(
56                     reportManager, reportNames));
57             }
58 
59             thresholds.emplace_back(std::make_shared<DiscreteThreshold>(
60                 bus->get_io_context(), sensors, sensorNames, std::move(actions),
61                 std::chrono::milliseconds(dwellTime), thresholdValue,
62                 thresholdName));
63         }
64         if (params.empty())
65         {
66             std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
67             if (logToJournal)
68             {
69                 actions.emplace_back(
70                     std::make_unique<
71                         action::discrete::onChange::LogToJournal>());
72             }
73             if (logToRedfish)
74             {
75                 actions.emplace_back(
76                     std::make_unique<
77                         action::discrete::onChange::LogToRedfish>());
78             }
79             if (updateReport)
80             {
81                 actions.emplace_back(std::make_unique<action::UpdateReport>(
82                     reportManager, reportNames));
83             }
84 
85             thresholds.emplace_back(std::make_shared<OnChangeThreshold>(
86                 sensors, sensorNames, std::move(actions)));
87         }
88     }
89     else
90     {
91         const auto& params =
92             std::get<std::vector<numeric::ThresholdParam>>(thresholdParams);
93         for (const auto& [typeStr, dwellTime, directionStr, value] : params)
94         {
95             numeric::Type type = numeric::stringToType(typeStr);
96             std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
97             if (logToJournal)
98             {
99                 actions.emplace_back(
100                     std::make_unique<action::numeric::LogToJournal>(type,
101                                                                     value));
102             }
103             if (logToRedfish)
104             {
105                 actions.emplace_back(
106                     std::make_unique<action::numeric::LogToRedfish>(type,
107                                                                     value));
108             }
109             if (updateReport)
110             {
111                 actions.emplace_back(std::make_unique<action::UpdateReport>(
112                     reportManager, reportNames));
113             }
114 
115             thresholds.emplace_back(std::make_shared<NumericThreshold>(
116                 bus->get_io_context(), sensors, sensorNames, std::move(actions),
117                 std::chrono::milliseconds(dwellTime),
118                 numeric::stringToDirection(directionStr), value));
119         }
120     }
121 
122     return std::make_unique<Trigger>(
123         bus->get_io_context(), objServer, name, isDiscrete, logToJournal,
124         logToRedfish, updateReport, sensorPaths, reportNames, thresholdParams,
125         std::move(thresholds), triggerManager, triggerStorage);
126 }
127 
128 std::pair<std::vector<std::shared_ptr<interfaces::Sensor>>,
129           std::vector<std::string>>
130     TriggerFactory::getSensors(
131         boost::asio::yield_context& yield,
132         const std::vector<std::pair<sdbusplus::message::object_path,
133                                     std::string>>& sensorPaths) const
134 {
135     auto tree = utils::getSubTreeSensors(yield, bus);
136 
137     std::vector<std::shared_ptr<interfaces::Sensor>> sensors;
138     std::vector<std::string> sensorNames;
139     for (const auto& [sensorPath, metadata] : sensorPaths)
140     {
141         auto found = std::find_if(
142             tree.begin(), tree.end(),
143             [&sensorPath](const auto& x) { return x.first == sensorPath; });
144         if (found == tree.end())
145         {
146             throw std::runtime_error("Not found");
147         }
148 
149         const auto& service = found->second[0].first;
150         const auto& path = found->first;
151         sensors.emplace_back(sensorCache.makeSensor<Sensor>(
152             service, path, bus->get_io_context(), bus));
153         if (metadata.empty())
154         {
155             sensorNames.emplace_back(sensorPath);
156         }
157         else
158         {
159             sensorNames.emplace_back(metadata);
160         }
161     }
162     return {sensors, sensorNames};
163 }
164