blob: 89ddfcc24564f11b10acfe64503acddf14d91336 [file] [log] [blame]
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +01001#include "trigger_actions.hpp"
2
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +01003#include "messages/update_report_ind.hpp"
4#include "utils/messanger.hpp"
5
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +01006#include <phosphor-logging/log.hpp>
7
8#include <ctime>
9
10namespace action
11{
12
Szymon Dompkef763c9e2021-03-12 09:19:22 +010013namespace
14{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010015std::string timestampToString(Milliseconds timestamp)
Szymon Dompkef763c9e2021-03-12 09:19:22 +010016{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010017 std::time_t t = static_cast<time_t>(timestamp.count());
Szymon Dompkef763c9e2021-03-12 09:19:22 +010018 std::array<char, sizeof("YYYY-MM-DDThh:mm:ssZ")> buf = {};
19 size_t size =
20 std::strftime(buf.data(), buf.size(), "%FT%TZ", std::gmtime(&t));
21 if (size == 0)
22 {
23 throw std::runtime_error("Failed to parse timestamp to string");
24 }
25 return std::string(buf.data(), size);
26}
27} // namespace
28
29namespace numeric
30{
31
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010032static const char* getDirection(double value, double threshold)
33{
34 if (value < threshold)
35 {
36 return "decreasing";
37 }
38 if (value > threshold)
39 {
40 return "increasing";
41 }
42 throw std::runtime_error("Invalid value");
43}
44
45const char* LogToJournal::getType() const
46{
47 switch (type)
48 {
Szymon Dompkef763c9e2021-03-12 09:19:22 +010049 case ::numeric::Type::upperCritical:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010050 return "UpperCritical";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010051 case ::numeric::Type::lowerCritical:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010052 return "LowerCritical";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010053 case ::numeric::Type::upperWarning:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010054 return "UpperWarning";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010055 case ::numeric::Type::lowerWarning:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010056 return "LowerWarning";
57 }
58 throw std::runtime_error("Invalid type");
59}
60
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010061void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp,
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010062 double value)
63{
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010064 std::string msg = std::string(getType()) +
65 " numeric threshold condition is met on sensor " +
66 sensorName + ", recorded value " + std::to_string(value) +
Szymon Dompkef763c9e2021-03-12 09:19:22 +010067 ", timestamp " + timestampToString(timestamp) +
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010068 ", direction " +
69 std::string(getDirection(value, threshold));
70
71 phosphor::logging::log<phosphor::logging::level::INFO>(msg.c_str());
72}
73
74const char* LogToRedfish::getMessageId() const
75{
76 switch (type)
77 {
Szymon Dompkef763c9e2021-03-12 09:19:22 +010078 case ::numeric::Type::upperCritical:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010079 return "OpenBMC.0.1.0.NumericThresholdUpperCritical";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010080 case ::numeric::Type::lowerCritical:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010081 return "OpenBMC.0.1.0.NumericThresholdLowerCritical";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010082 case ::numeric::Type::upperWarning:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010083 return "OpenBMC.0.1.0.NumericThresholdUpperWarning";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010084 case ::numeric::Type::lowerWarning:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010085 return "OpenBMC.0.1.0.NumericThresholdLowerWarning";
86 }
87 throw std::runtime_error("Invalid type");
88}
89
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010090void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp,
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010091 double value)
92{
93 phosphor::logging::log<phosphor::logging::level::INFO>(
94 "Threshold value is exceeded",
95 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", getMessageId()),
96 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu,%s",
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010097 sensorName.c_str(), value, timestamp.count(),
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010098 getDirection(value, threshold)));
99}
100
Szymon Dompke20013012021-07-23 09:54:20 +0200101void fillActions(
102 std::vector<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
103 const std::vector<TriggerAction>& ActionsEnum, ::numeric::Type type,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100104 double thresholdValue, boost::asio::io_context& ioc,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100105 const std::shared_ptr<std::vector<std::string>>& reportIds)
Szymon Dompke20013012021-07-23 09:54:20 +0200106{
107 actionsIf.reserve(ActionsEnum.size());
108 for (auto actionType : ActionsEnum)
109 {
110 switch (actionType)
111 {
112 case TriggerAction::LogToLogService:
113 {
114 actionsIf.emplace_back(
115 std::make_unique<LogToJournal>(type, thresholdValue));
116 break;
117 }
118 case TriggerAction::RedfishEvent:
119 {
120 actionsIf.emplace_back(
121 std::make_unique<LogToRedfish>(type, thresholdValue));
122 break;
123 }
124 case TriggerAction::UpdateReport:
125 {
126 actionsIf.emplace_back(
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100127 std::make_unique<UpdateReport>(ioc, reportIds));
Szymon Dompke20013012021-07-23 09:54:20 +0200128 break;
129 }
130 }
131 }
132}
133
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100134} // namespace numeric
135
136namespace discrete
137{
138const char* LogToJournal::getSeverity() const
139{
140 switch (severity)
141 {
142 case ::discrete::Severity::ok:
143 return "OK";
144 case ::discrete::Severity::warning:
145 return "Warning";
146 case ::discrete::Severity::critical:
147 return "Critical";
148 }
149 throw std::runtime_error("Invalid severity");
150}
151
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100152void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100153 double value)
154{
155 std::string msg = std::string(getSeverity()) +
156 " discrete threshold condition is met on sensor " +
157 sensorName + ", recorded value " + std::to_string(value) +
158 ", timestamp " + timestampToString(timestamp);
159
160 phosphor::logging::log<phosphor::logging::level::INFO>(msg.c_str());
161}
162
163const char* LogToRedfish::getMessageId() const
164{
165 switch (severity)
166 {
167 case ::discrete::Severity::ok:
168 return "OpenBMC.0.1.0.DiscreteThresholdOk";
169 case ::discrete::Severity::warning:
170 return "OpenBMC.0.1.0.DiscreteThresholdWarning";
171 case ::discrete::Severity::critical:
172 return "OpenBMC.0.1.0.DiscreteThresholdCritical";
173 }
174 throw std::runtime_error("Invalid severity");
175}
176
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100177void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100178 double value)
179{
180 phosphor::logging::log<phosphor::logging::level::INFO>(
181 "Discrete treshold condition is met",
182 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", getMessageId()),
183 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu",
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100184 sensorName.c_str(), value, timestamp.count()));
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100185}
186
Szymon Dompke20013012021-07-23 09:54:20 +0200187void fillActions(
188 std::vector<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
189 const std::vector<TriggerAction>& ActionsEnum,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100190 ::discrete::Severity severity, boost::asio::io_context& ioc,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100191 const std::shared_ptr<std::vector<std::string>>& reportIds)
Szymon Dompke20013012021-07-23 09:54:20 +0200192{
193 actionsIf.reserve(ActionsEnum.size());
194 for (auto actionType : ActionsEnum)
195 {
196 switch (actionType)
197 {
198 case TriggerAction::LogToLogService:
199 {
200 actionsIf.emplace_back(
201 std::make_unique<LogToJournal>(severity));
202 break;
203 }
204 case TriggerAction::RedfishEvent:
205 {
206 actionsIf.emplace_back(
207 std::make_unique<LogToRedfish>(severity));
208 break;
209 }
210 case TriggerAction::UpdateReport:
211 {
212 actionsIf.emplace_back(
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100213 std::make_unique<UpdateReport>(ioc, reportIds));
Szymon Dompke20013012021-07-23 09:54:20 +0200214 break;
215 }
216 }
217 }
218}
219
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100220namespace onChange
221{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100222void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100223 double value)
224{
225 std::string msg = "Value changed on sensor " + sensorName +
226 ", recorded value " + std::to_string(value) +
227 ", timestamp " + timestampToString(timestamp);
228
229 phosphor::logging::log<phosphor::logging::level::INFO>(msg.c_str());
230}
231
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100232void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100233 double value)
234{
235 const char* messageId = "OpenBMC.0.1.0.DiscreteThresholdOnChange";
236 phosphor::logging::log<phosphor::logging::level::INFO>(
237 "Uncondtional discrete threshold triggered",
238 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageId),
239 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu",
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100240 sensorName.c_str(), value, timestamp.count()));
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100241}
Szymon Dompke20013012021-07-23 09:54:20 +0200242
243void fillActions(
244 std::vector<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100245 const std::vector<TriggerAction>& ActionsEnum, boost::asio::io_context& ioc,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100246 const std::shared_ptr<std::vector<std::string>>& reportIds)
Szymon Dompke20013012021-07-23 09:54:20 +0200247{
248 actionsIf.reserve(ActionsEnum.size());
249 for (auto actionType : ActionsEnum)
250 {
251 switch (actionType)
252 {
253 case TriggerAction::LogToLogService:
254 {
255 actionsIf.emplace_back(std::make_unique<LogToJournal>());
256 break;
257 }
258 case TriggerAction::RedfishEvent:
259 {
260 actionsIf.emplace_back(std::make_unique<LogToRedfish>());
261 break;
262 }
263 case TriggerAction::UpdateReport:
264 {
265 actionsIf.emplace_back(
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100266 std::make_unique<UpdateReport>(ioc, reportIds));
Szymon Dompke20013012021-07-23 09:54:20 +0200267 break;
268 }
269 }
270 }
271}
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100272} // namespace onChange
273} // namespace discrete
274
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100275void UpdateReport::commit(const std::string&, Milliseconds, double)
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100276{
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100277 if (reportIds->empty())
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100278 {
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100279 return;
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100280 }
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100281
282 utils::Messanger messanger(ioc);
283 messanger.send(messages::UpdateReportInd{*reportIds});
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100284}
285} // namespace action