#include "trigger_actions.hpp" #include "messages/update_report_ind.hpp" #include "types/trigger_types.hpp" #include "utils/clock.hpp" #include "utils/messanger.hpp" #include "utils/to_short_enum.hpp" #include #include #include #include namespace action { namespace { std::string timestampToString(Milliseconds timestamp) { std::time_t t = static_cast( std::chrono::duration_cast(timestamp).count()); std::stringstream ss; ss << std::put_time(std::gmtime(&t), "%FT%T.") << std::setw(3) << std::setfill('0') << timestamp.count() % 1000 << 'Z'; return ss.str(); } } // 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& triggerId, const ThresholdName thresholdNameInIn, const std::string& sensorName, const Milliseconds timestamp, const TriggerValue triggerValue) { double value = std::get(triggerValue); std::string thresholdName = ::numeric::typeToString(type); auto direction = getDirection(value, threshold); std::string msg = "Numeric threshold '" + std::string(utils::toShortEnum(thresholdName)) + "' of trigger '" + triggerId + "' is crossed on sensor " + sensorName + ", recorded value: " + std::to_string(value) + ", crossing direction: " + std::string(utils::toShortEnum(direction)) + ", timestamp: " + timestampToString(timestamp); phosphor::logging::log(msg.c_str()); } const char* LogToRedfishEventLog::getRedfishMessageId(const double value) const { std::string direction(getDirection(value, threshold)); if (direction == "decreasing") { switch (type) { case ::numeric::Type::upperCritical: return redfish_message_ids::TriggerNumericBelowUpperCritical; case ::numeric::Type::lowerCritical: return redfish_message_ids::TriggerNumericBelowLowerCritical; case ::numeric::Type::upperWarning: return redfish_message_ids::TriggerNumericReadingNormal; case ::numeric::Type::lowerWarning: return redfish_message_ids::TriggerNumericBelowLowerWarning; } } if (direction == "increasing") { switch (type) { case ::numeric::Type::upperCritical: return redfish_message_ids::TriggerNumericAboveUpperCritical; case ::numeric::Type::lowerCritical: return redfish_message_ids::TriggerNumericAboveLowerCritical; case ::numeric::Type::upperWarning: return redfish_message_ids::TriggerNumericAboveUpperWarning; case ::numeric::Type::lowerWarning: return redfish_message_ids::TriggerNumericReadingNormal; } } throw std::runtime_error("Invalid type"); } void LogToRedfishEventLog::commit(const std::string& triggerId, const ThresholdName thresholdNameInIn, const std::string& sensorName, const Milliseconds timestamp, const TriggerValue triggerValue) { double value = std::get(triggerValue); auto messageId = getRedfishMessageId(value); if (messageId == redfish_message_ids::TriggerNumericReadingNormal) { phosphor::logging::log( "Logging numeric trigger action to Redfish Event Log.", phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageId), phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%s", sensorName.c_str(), value, triggerId.c_str())); } else { phosphor::logging::log( "Logging numeric trigger action to Redfish Event Log.", phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageId), phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%f,%f,%s", sensorName.c_str(), value, threshold, triggerId.c_str())); } } 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::LogToJournal: { actionsIf.emplace_back( std::make_unique(type, thresholdValue)); break; } case TriggerAction::LogToRedfishEventLog: { 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& triggerId, const ThresholdName thresholdNameIn, const std::string& sensorName, const Milliseconds timestamp, const TriggerValue triggerValue) { auto value = std::get(triggerValue); std::string msg = "Discrete condition '" + thresholdNameIn->get() + "' of trigger '" + triggerId + "' is met on sensor " + sensorName + ", recorded value: " + value + ", severity: " + std::string(utils::toShortEnum(utils::enumToString(severity))) + ", timestamp: " + timestampToString(timestamp); phosphor::logging::log(msg.c_str()); } void LogToRedfishEventLog::commit(const std::string& triggerId, const ThresholdName thresholdNameIn, const std::string& sensorName, const Milliseconds timestamp, const TriggerValue triggerValue) { auto value = std::get(triggerValue); phosphor::logging::log( "Logging discrete trigger action to Redfish Event Log.", phosphor::logging::entry( "REDFISH_MESSAGE_ID=%s", redfish_message_ids::TriggerDiscreteConditionMet), phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%s,%s", sensorName.c_str(), value.c_str(), triggerId.c_str())); } 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::LogToJournal: { actionsIf.emplace_back( std::make_unique(severity)); break; } case TriggerAction::LogToRedfishEventLog: { actionsIf.emplace_back( std::make_unique()); break; } case TriggerAction::UpdateReport: { actionsIf.emplace_back( std::make_unique(ioc, reportIds)); break; } } } } namespace onChange { void LogToJournal::commit(const std::string& triggerId, const ThresholdName thresholdNameIn, const std::string& sensorName, const Milliseconds timestamp, const TriggerValue triggerValue) { auto value = triggerValueToString(triggerValue); std::string msg = "Discrete condition 'OnChange' of trigger '" + triggerId + "' is met on sensor: " + sensorName + ", recorded value: " + value + ", timestamp: " + timestampToString(timestamp); phosphor::logging::log(msg.c_str()); } void LogToRedfishEventLog::commit(const std::string& triggerId, const ThresholdName thresholdNameIn, const std::string& sensorName, const Milliseconds timestamp, const TriggerValue triggerValue) { auto value = triggerValueToString(triggerValue); phosphor::logging::log( "Logging onChange discrete trigger action to Redfish Event Log.", phosphor::logging::entry( "REDFISH_MESSAGE_ID=%s", redfish_message_ids::TriggerDiscreteConditionMet), phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s,%s,%s", sensorName.c_str(), value.c_str(), triggerId.c_str())); } 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::LogToJournal: { actionsIf.emplace_back(std::make_unique()); break; } case TriggerAction::LogToRedfishEventLog: { 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& triggerId, const ThresholdName thresholdNameIn, const std::string& sensorName, const Milliseconds timestamp, const TriggerValue triggerValue) { if (reportIds->empty()) { return; } utils::Messanger messanger(ioc); messanger.send(messages::UpdateReportInd{*reportIds}); } } // namespace action