#include "trigger_actions.hpp" #include "messages/update_report_ind.hpp" #include "types/trigger_types.hpp" #include "utils/messanger.hpp" #include #include namespace action { namespace { std::string timestampToString(Milliseconds timestamp) { std::time_t t = static_cast(timestamp.count()); std::array buf = {}; size_t size = std::strftime(buf.data(), buf.size(), "%FT%TZ", std::gmtime(&t)); if (size == 0) { throw std::runtime_error("Failed to parse timestamp to string"); } return std::string(buf.data(), size); } } // namespace namespace numeric { static const char* getDirection(double value, double threshold) { if (value < threshold) { return "decreasing"; } if (value > threshold) { return "increasing"; } throw std::runtime_error("Invalid value"); } void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp, double value) { std::string msg = ::numeric::typeToString(type) + " numeric threshold condition is met on sensor " + sensorName + ", recorded value " + std::to_string(value) + ", timestamp " + timestampToString(timestamp) + ", direction " + std::string(getDirection(value, threshold)); phosphor::logging::log(msg.c_str()); } const char* LogToRedfish::getMessageId() const { switch (type) { case ::numeric::Type::upperCritical: return "OpenBMC.0.1.0.NumericThresholdUpperCritical"; case ::numeric::Type::lowerCritical: return "OpenBMC.0.1.0.NumericThresholdLowerCritical"; case ::numeric::Type::upperWarning: return "OpenBMC.0.1.0.NumericThresholdUpperWarning"; case ::numeric::Type::lowerWarning: return "OpenBMC.0.1.0.NumericThresholdLowerWarning"; } throw std::runtime_error("Invalid type"); } void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp, double value) { phosphor::logging::log( "Threshold value is exceeded", phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", getMessageId()), phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu,%s", sensorName.c_str(), value, timestamp.count(), getDirection(value, threshold))); } void fillActions( std::vector>& actionsIf, const std::vector& ActionsEnum, ::numeric::Type type, double thresholdValue, boost::asio::io_context& ioc, const std::shared_ptr>& reportIds) { actionsIf.reserve(ActionsEnum.size()); for (auto actionType : ActionsEnum) { switch (actionType) { case TriggerAction::LogToLogService: { actionsIf.emplace_back( std::make_unique(type, thresholdValue)); break; } case TriggerAction::RedfishEvent: { actionsIf.emplace_back( std::make_unique(type, thresholdValue)); break; } case TriggerAction::UpdateReport: { actionsIf.emplace_back( std::make_unique(ioc, reportIds)); break; } } } } } // namespace numeric namespace discrete { void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp, double value) { std::string msg = ::discrete::severityToString(severity) + " discrete threshold condition is met on sensor " + sensorName + ", recorded value " + std::to_string(value) + ", timestamp " + timestampToString(timestamp); phosphor::logging::log(msg.c_str()); } const char* LogToRedfish::getMessageId() const { switch (severity) { case ::discrete::Severity::ok: return "OpenBMC.0.1.0.DiscreteThresholdOk"; case ::discrete::Severity::warning: return "OpenBMC.0.1.0.DiscreteThresholdWarning"; case ::discrete::Severity::critical: return "OpenBMC.0.1.0.DiscreteThresholdCritical"; } throw std::runtime_error("Invalid severity"); } void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp, double value) { phosphor::logging::log( "Discrete treshold condition is met", phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", getMessageId()), phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu", sensorName.c_str(), value, timestamp.count())); } void fillActions( std::vector>& actionsIf, const std::vector& ActionsEnum, ::discrete::Severity severity, boost::asio::io_context& ioc, const std::shared_ptr>& reportIds) { actionsIf.reserve(ActionsEnum.size()); for (auto actionType : ActionsEnum) { switch (actionType) { case TriggerAction::LogToLogService: { actionsIf.emplace_back( std::make_unique(severity)); break; } case TriggerAction::RedfishEvent: { actionsIf.emplace_back( std::make_unique(severity)); break; } case TriggerAction::UpdateReport: { actionsIf.emplace_back( std::make_unique(ioc, reportIds)); break; } } } } namespace onChange { void LogToJournal::commit(const std::string& sensorName, Milliseconds timestamp, double value) { std::string msg = "Value changed on sensor " + sensorName + ", recorded value " + std::to_string(value) + ", timestamp " + timestampToString(timestamp); phosphor::logging::log(msg.c_str()); } void LogToRedfish::commit(const std::string& sensorName, Milliseconds timestamp, double value) { const char* messageId = "OpenBMC.0.1.0.DiscreteThresholdOnChange"; phosphor::logging::log( "Uncondtional discrete threshold triggered", phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageId), phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%llu", sensorName.c_str(), value, timestamp.count())); } void fillActions( std::vector>& actionsIf, const std::vector& ActionsEnum, boost::asio::io_context& ioc, const std::shared_ptr>& reportIds) { actionsIf.reserve(ActionsEnum.size()); for (auto actionType : ActionsEnum) { switch (actionType) { case TriggerAction::LogToLogService: { actionsIf.emplace_back(std::make_unique()); break; } case TriggerAction::RedfishEvent: { actionsIf.emplace_back(std::make_unique()); break; } case TriggerAction::UpdateReport: { actionsIf.emplace_back( std::make_unique(ioc, reportIds)); break; } } } } } // namespace onChange } // namespace discrete void UpdateReport::commit(const std::string&, Milliseconds, double) { if (reportIds->empty()) { return; } utils::Messanger messanger(ioc); messanger.send(messages::UpdateReportInd{*reportIds}); } } // namespace action