blob: c8404223616b28ed72dd3dcf6c62f786b7b708b6 [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"
Szymon Dompkef670b022022-03-16 19:21:11 +01004#include "types/trigger_types.hpp"
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +01005#include "utils/messanger.hpp"
6
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +01007#include <phosphor-logging/log.hpp>
8
9#include <ctime>
10
11namespace action
12{
13
Szymon Dompkef763c9e2021-03-12 09:19:22 +010014namespace
15{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010016std::string timestampToString(Milliseconds timestamp)
Szymon Dompkef763c9e2021-03-12 09:19:22 +010017{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010018 std::time_t t = static_cast<time_t>(timestamp.count());
Szymon Dompkef763c9e2021-03-12 09:19:22 +010019 std::array<char, sizeof("YYYY-MM-DDThh:mm:ssZ")> buf = {};
20 size_t size =
21 std::strftime(buf.data(), buf.size(), "%FT%TZ", std::gmtime(&t));
22 if (size == 0)
23 {
24 throw std::runtime_error("Failed to parse timestamp to string");
25 }
26 return std::string(buf.data(), size);
27}
28} // namespace
29
30namespace numeric
31{
32
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010033static const char* getDirection(double value, double threshold)
34{
35 if (value < threshold)
36 {
37 return "decreasing";
38 }
39 if (value > threshold)
40 {
41 return "increasing";
42 }
43 throw std::runtime_error("Invalid value");
44}
45
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010046void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp,
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010047 double value)
48{
Szymon Dompkef670b022022-03-16 19:21:11 +010049 std::string msg = ::numeric::typeToString(type) +
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010050 " numeric threshold condition is met on sensor " +
51 sensorName + ", recorded value " + std::to_string(value) +
Szymon Dompkef763c9e2021-03-12 09:19:22 +010052 ", timestamp " + timestampToString(timestamp) +
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010053 ", direction " +
54 std::string(getDirection(value, threshold));
55
56 phosphor::logging::log<phosphor::logging::level::INFO>(msg.c_str());
57}
58
59const char* LogToRedfish::getMessageId() const
60{
61 switch (type)
62 {
Szymon Dompkef763c9e2021-03-12 09:19:22 +010063 case ::numeric::Type::upperCritical:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010064 return "OpenBMC.0.1.0.NumericThresholdUpperCritical";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010065 case ::numeric::Type::lowerCritical:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010066 return "OpenBMC.0.1.0.NumericThresholdLowerCritical";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010067 case ::numeric::Type::upperWarning:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010068 return "OpenBMC.0.1.0.NumericThresholdUpperWarning";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010069 case ::numeric::Type::lowerWarning:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010070 return "OpenBMC.0.1.0.NumericThresholdLowerWarning";
71 }
72 throw std::runtime_error("Invalid type");
73}
74
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010075void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp,
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010076 double value)
77{
78 phosphor::logging::log<phosphor::logging::level::INFO>(
79 "Threshold value is exceeded",
80 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", getMessageId()),
81 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu,%s",
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010082 sensorName.c_str(), value, timestamp.count(),
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010083 getDirection(value, threshold)));
84}
85
Szymon Dompke20013012021-07-23 09:54:20 +020086void fillActions(
87 std::vector<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
88 const std::vector<TriggerAction>& ActionsEnum, ::numeric::Type type,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010089 double thresholdValue, boost::asio::io_context& ioc,
Szymon Dompke94f71c52021-12-10 07:16:33 +010090 const std::shared_ptr<std::vector<std::string>>& reportIds)
Szymon Dompke20013012021-07-23 09:54:20 +020091{
92 actionsIf.reserve(ActionsEnum.size());
93 for (auto actionType : ActionsEnum)
94 {
95 switch (actionType)
96 {
97 case TriggerAction::LogToLogService:
98 {
99 actionsIf.emplace_back(
100 std::make_unique<LogToJournal>(type, thresholdValue));
101 break;
102 }
103 case TriggerAction::RedfishEvent:
104 {
105 actionsIf.emplace_back(
106 std::make_unique<LogToRedfish>(type, thresholdValue));
107 break;
108 }
109 case TriggerAction::UpdateReport:
110 {
111 actionsIf.emplace_back(
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100112 std::make_unique<UpdateReport>(ioc, reportIds));
Szymon Dompke20013012021-07-23 09:54:20 +0200113 break;
114 }
115 }
116 }
117}
118
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100119} // namespace numeric
120
121namespace discrete
122{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100123void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100124 double value)
125{
Szymon Dompkef670b022022-03-16 19:21:11 +0100126 std::string msg = ::discrete::severityToString(severity) +
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100127 " discrete threshold condition is met on sensor " +
128 sensorName + ", recorded value " + std::to_string(value) +
129 ", timestamp " + timestampToString(timestamp);
130
131 phosphor::logging::log<phosphor::logging::level::INFO>(msg.c_str());
132}
133
134const char* LogToRedfish::getMessageId() const
135{
136 switch (severity)
137 {
138 case ::discrete::Severity::ok:
139 return "OpenBMC.0.1.0.DiscreteThresholdOk";
140 case ::discrete::Severity::warning:
141 return "OpenBMC.0.1.0.DiscreteThresholdWarning";
142 case ::discrete::Severity::critical:
143 return "OpenBMC.0.1.0.DiscreteThresholdCritical";
144 }
145 throw std::runtime_error("Invalid severity");
146}
147
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100148void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100149 double value)
150{
151 phosphor::logging::log<phosphor::logging::level::INFO>(
152 "Discrete treshold condition is met",
153 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", getMessageId()),
154 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu",
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100155 sensorName.c_str(), value, timestamp.count()));
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100156}
157
Szymon Dompke20013012021-07-23 09:54:20 +0200158void fillActions(
159 std::vector<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
160 const std::vector<TriggerAction>& ActionsEnum,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100161 ::discrete::Severity severity, boost::asio::io_context& ioc,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100162 const std::shared_ptr<std::vector<std::string>>& reportIds)
Szymon Dompke20013012021-07-23 09:54:20 +0200163{
164 actionsIf.reserve(ActionsEnum.size());
165 for (auto actionType : ActionsEnum)
166 {
167 switch (actionType)
168 {
169 case TriggerAction::LogToLogService:
170 {
171 actionsIf.emplace_back(
172 std::make_unique<LogToJournal>(severity));
173 break;
174 }
175 case TriggerAction::RedfishEvent:
176 {
177 actionsIf.emplace_back(
178 std::make_unique<LogToRedfish>(severity));
179 break;
180 }
181 case TriggerAction::UpdateReport:
182 {
183 actionsIf.emplace_back(
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100184 std::make_unique<UpdateReport>(ioc, reportIds));
Szymon Dompke20013012021-07-23 09:54:20 +0200185 break;
186 }
187 }
188 }
189}
190
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100191namespace onChange
192{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100193void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100194 double value)
195{
196 std::string msg = "Value changed on sensor " + sensorName +
197 ", recorded value " + std::to_string(value) +
198 ", timestamp " + timestampToString(timestamp);
199
200 phosphor::logging::log<phosphor::logging::level::INFO>(msg.c_str());
201}
202
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100203void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100204 double value)
205{
206 const char* messageId = "OpenBMC.0.1.0.DiscreteThresholdOnChange";
207 phosphor::logging::log<phosphor::logging::level::INFO>(
208 "Uncondtional discrete threshold triggered",
209 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageId),
210 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu",
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100211 sensorName.c_str(), value, timestamp.count()));
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100212}
Szymon Dompke20013012021-07-23 09:54:20 +0200213
214void fillActions(
215 std::vector<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100216 const std::vector<TriggerAction>& ActionsEnum, boost::asio::io_context& ioc,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100217 const std::shared_ptr<std::vector<std::string>>& reportIds)
Szymon Dompke20013012021-07-23 09:54:20 +0200218{
219 actionsIf.reserve(ActionsEnum.size());
220 for (auto actionType : ActionsEnum)
221 {
222 switch (actionType)
223 {
224 case TriggerAction::LogToLogService:
225 {
226 actionsIf.emplace_back(std::make_unique<LogToJournal>());
227 break;
228 }
229 case TriggerAction::RedfishEvent:
230 {
231 actionsIf.emplace_back(std::make_unique<LogToRedfish>());
232 break;
233 }
234 case TriggerAction::UpdateReport:
235 {
236 actionsIf.emplace_back(
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100237 std::make_unique<UpdateReport>(ioc, reportIds));
Szymon Dompke20013012021-07-23 09:54:20 +0200238 break;
239 }
240 }
241 }
242}
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100243} // namespace onChange
244} // namespace discrete
245
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100246void UpdateReport::commit(const std::string&, Milliseconds, double)
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100247{
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100248 if (reportIds->empty())
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100249 {
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100250 return;
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100251 }
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100252
253 utils::Messanger messanger(ioc);
254 messanger.send(messages::UpdateReportInd{*reportIds});
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100255}
256} // namespace action