blob: 0a627e6d7de5131560b11ddefd4b538900ebd24e [file] [log] [blame]
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +01001#include "trigger_actions.hpp"
2
3#include <phosphor-logging/log.hpp>
4
5#include <ctime>
6
7namespace action
8{
9
Szymon Dompkef763c9e2021-03-12 09:19:22 +010010namespace
11{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010012std::string timestampToString(Milliseconds timestamp)
Szymon Dompkef763c9e2021-03-12 09:19:22 +010013{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010014 std::time_t t = static_cast<time_t>(timestamp.count());
Szymon Dompkef763c9e2021-03-12 09:19:22 +010015 std::array<char, sizeof("YYYY-MM-DDThh:mm:ssZ")> buf = {};
16 size_t size =
17 std::strftime(buf.data(), buf.size(), "%FT%TZ", std::gmtime(&t));
18 if (size == 0)
19 {
20 throw std::runtime_error("Failed to parse timestamp to string");
21 }
22 return std::string(buf.data(), size);
23}
24} // namespace
25
26namespace numeric
27{
28
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010029static const char* getDirection(double value, double threshold)
30{
31 if (value < threshold)
32 {
33 return "decreasing";
34 }
35 if (value > threshold)
36 {
37 return "increasing";
38 }
39 throw std::runtime_error("Invalid value");
40}
41
42const char* LogToJournal::getType() const
43{
44 switch (type)
45 {
Szymon Dompkef763c9e2021-03-12 09:19:22 +010046 case ::numeric::Type::upperCritical:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010047 return "UpperCritical";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010048 case ::numeric::Type::lowerCritical:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010049 return "LowerCritical";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010050 case ::numeric::Type::upperWarning:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010051 return "UpperWarning";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010052 case ::numeric::Type::lowerWarning:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010053 return "LowerWarning";
54 }
55 throw std::runtime_error("Invalid type");
56}
57
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010058void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp,
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010059 double value)
60{
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010061 std::string msg = std::string(getType()) +
62 " numeric threshold condition is met on sensor " +
63 sensorName + ", recorded value " + std::to_string(value) +
Szymon Dompkef763c9e2021-03-12 09:19:22 +010064 ", timestamp " + timestampToString(timestamp) +
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010065 ", direction " +
66 std::string(getDirection(value, threshold));
67
68 phosphor::logging::log<phosphor::logging::level::INFO>(msg.c_str());
69}
70
71const char* LogToRedfish::getMessageId() const
72{
73 switch (type)
74 {
Szymon Dompkef763c9e2021-03-12 09:19:22 +010075 case ::numeric::Type::upperCritical:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010076 return "OpenBMC.0.1.0.NumericThresholdUpperCritical";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010077 case ::numeric::Type::lowerCritical:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010078 return "OpenBMC.0.1.0.NumericThresholdLowerCritical";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010079 case ::numeric::Type::upperWarning:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010080 return "OpenBMC.0.1.0.NumericThresholdUpperWarning";
Szymon Dompkef763c9e2021-03-12 09:19:22 +010081 case ::numeric::Type::lowerWarning:
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010082 return "OpenBMC.0.1.0.NumericThresholdLowerWarning";
83 }
84 throw std::runtime_error("Invalid type");
85}
86
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010087void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp,
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010088 double value)
89{
90 phosphor::logging::log<phosphor::logging::level::INFO>(
91 "Threshold value is exceeded",
92 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", getMessageId()),
93 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu,%s",
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010094 sensorName.c_str(), value, timestamp.count(),
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010095 getDirection(value, threshold)));
96}
97
Szymon Dompke20013012021-07-23 09:54:20 +020098void fillActions(
99 std::vector<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
100 const std::vector<TriggerAction>& ActionsEnum, ::numeric::Type type,
101 double thresholdValue, interfaces::ReportManager& reportManager,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100102 const std::shared_ptr<std::vector<std::string>>& reportIds)
Szymon Dompke20013012021-07-23 09:54:20 +0200103{
104 actionsIf.reserve(ActionsEnum.size());
105 for (auto actionType : ActionsEnum)
106 {
107 switch (actionType)
108 {
109 case TriggerAction::LogToLogService:
110 {
111 actionsIf.emplace_back(
112 std::make_unique<LogToJournal>(type, thresholdValue));
113 break;
114 }
115 case TriggerAction::RedfishEvent:
116 {
117 actionsIf.emplace_back(
118 std::make_unique<LogToRedfish>(type, thresholdValue));
119 break;
120 }
121 case TriggerAction::UpdateReport:
122 {
123 actionsIf.emplace_back(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100124 std::make_unique<UpdateReport>(reportManager, reportIds));
Szymon Dompke20013012021-07-23 09:54:20 +0200125 break;
126 }
127 }
128 }
129}
130
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100131} // namespace numeric
132
133namespace discrete
134{
135const char* LogToJournal::getSeverity() const
136{
137 switch (severity)
138 {
139 case ::discrete::Severity::ok:
140 return "OK";
141 case ::discrete::Severity::warning:
142 return "Warning";
143 case ::discrete::Severity::critical:
144 return "Critical";
145 }
146 throw std::runtime_error("Invalid severity");
147}
148
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100149void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100150 double value)
151{
152 std::string msg = std::string(getSeverity()) +
153 " discrete threshold condition is met on sensor " +
154 sensorName + ", recorded value " + std::to_string(value) +
155 ", timestamp " + timestampToString(timestamp);
156
157 phosphor::logging::log<phosphor::logging::level::INFO>(msg.c_str());
158}
159
160const char* LogToRedfish::getMessageId() const
161{
162 switch (severity)
163 {
164 case ::discrete::Severity::ok:
165 return "OpenBMC.0.1.0.DiscreteThresholdOk";
166 case ::discrete::Severity::warning:
167 return "OpenBMC.0.1.0.DiscreteThresholdWarning";
168 case ::discrete::Severity::critical:
169 return "OpenBMC.0.1.0.DiscreteThresholdCritical";
170 }
171 throw std::runtime_error("Invalid severity");
172}
173
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100174void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100175 double value)
176{
177 phosphor::logging::log<phosphor::logging::level::INFO>(
178 "Discrete treshold condition is met",
179 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", getMessageId()),
180 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu",
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100181 sensorName.c_str(), value, timestamp.count()));
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100182}
183
Szymon Dompke20013012021-07-23 09:54:20 +0200184void fillActions(
185 std::vector<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
186 const std::vector<TriggerAction>& ActionsEnum,
187 ::discrete::Severity severity, interfaces::ReportManager& reportManager,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100188 const std::shared_ptr<std::vector<std::string>>& reportIds)
Szymon Dompke20013012021-07-23 09:54:20 +0200189{
190 actionsIf.reserve(ActionsEnum.size());
191 for (auto actionType : ActionsEnum)
192 {
193 switch (actionType)
194 {
195 case TriggerAction::LogToLogService:
196 {
197 actionsIf.emplace_back(
198 std::make_unique<LogToJournal>(severity));
199 break;
200 }
201 case TriggerAction::RedfishEvent:
202 {
203 actionsIf.emplace_back(
204 std::make_unique<LogToRedfish>(severity));
205 break;
206 }
207 case TriggerAction::UpdateReport:
208 {
209 actionsIf.emplace_back(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100210 std::make_unique<UpdateReport>(reportManager, reportIds));
Szymon Dompke20013012021-07-23 09:54:20 +0200211 break;
212 }
213 }
214 }
215}
216
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100217namespace onChange
218{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100219void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100220 double value)
221{
222 std::string msg = "Value changed on sensor " + sensorName +
223 ", recorded value " + std::to_string(value) +
224 ", timestamp " + timestampToString(timestamp);
225
226 phosphor::logging::log<phosphor::logging::level::INFO>(msg.c_str());
227}
228
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100229void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp,
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100230 double value)
231{
232 const char* messageId = "OpenBMC.0.1.0.DiscreteThresholdOnChange";
233 phosphor::logging::log<phosphor::logging::level::INFO>(
234 "Uncondtional discrete threshold triggered",
235 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageId),
236 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu",
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100237 sensorName.c_str(), value, timestamp.count()));
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100238}
Szymon Dompke20013012021-07-23 09:54:20 +0200239
240void fillActions(
241 std::vector<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
242 const std::vector<TriggerAction>& ActionsEnum,
243 interfaces::ReportManager& reportManager,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100244 const std::shared_ptr<std::vector<std::string>>& reportIds)
Szymon Dompke20013012021-07-23 09:54:20 +0200245{
246 actionsIf.reserve(ActionsEnum.size());
247 for (auto actionType : ActionsEnum)
248 {
249 switch (actionType)
250 {
251 case TriggerAction::LogToLogService:
252 {
253 actionsIf.emplace_back(std::make_unique<LogToJournal>());
254 break;
255 }
256 case TriggerAction::RedfishEvent:
257 {
258 actionsIf.emplace_back(std::make_unique<LogToRedfish>());
259 break;
260 }
261 case TriggerAction::UpdateReport:
262 {
263 actionsIf.emplace_back(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100264 std::make_unique<UpdateReport>(reportManager, reportIds));
Szymon Dompke20013012021-07-23 09:54:20 +0200265 break;
266 }
267 }
268 }
269}
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100270} // namespace onChange
271} // namespace discrete
272
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100273void UpdateReport::commit(const std::string&, Milliseconds, double)
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100274{
Szymon Dompke94f71c52021-12-10 07:16:33 +0100275 for (const auto& name : *reportIds)
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100276 {
277 reportManager.updateReport(name);
278 }
279}
280} // namespace action