blob: 9466b77b927ad0bd1c1528f509e3854c6589ef4b [file] [log] [blame]
#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 <phosphor-logging/log.hpp>
#include <ctime>
#include <iomanip>
#include <sstream>
namespace action
{
namespace
{
std::string timestampToString(Milliseconds timestamp)
{
std::time_t t = static_cast<time_t>(
std::chrono::duration_cast<std::chrono::seconds>(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<double>(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<phosphor::logging::level::INFO>(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<double>(triggerValue);
auto messageId = getRedfishMessageId(value);
if (messageId == redfish_message_ids::TriggerNumericReadingNormal)
{
phosphor::logging::log<phosphor::logging::level::INFO>(
"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<phosphor::logging::level::INFO>(
"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<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
const std::vector<TriggerAction>& ActionsEnum, ::numeric::Type type,
double thresholdValue, boost::asio::io_context& ioc,
const std::shared_ptr<std::vector<std::string>>& reportIds)
{
actionsIf.reserve(ActionsEnum.size());
for (auto actionType : ActionsEnum)
{
switch (actionType)
{
case TriggerAction::LogToJournal:
{
actionsIf.emplace_back(
std::make_unique<LogToJournal>(type, thresholdValue));
break;
}
case TriggerAction::LogToRedfishEventLog:
{
actionsIf.emplace_back(std::make_unique<LogToRedfishEventLog>(
type, thresholdValue));
break;
}
case TriggerAction::UpdateReport:
{
actionsIf.emplace_back(
std::make_unique<UpdateReport>(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<std::string>(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<phosphor::logging::level::INFO>(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<std::string>(triggerValue);
phosphor::logging::log<phosphor::logging::level::INFO>(
"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<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
const std::vector<TriggerAction>& ActionsEnum,
::discrete::Severity severity, boost::asio::io_context& ioc,
const std::shared_ptr<std::vector<std::string>>& reportIds)
{
actionsIf.reserve(ActionsEnum.size());
for (auto actionType : ActionsEnum)
{
switch (actionType)
{
case TriggerAction::LogToJournal:
{
actionsIf.emplace_back(
std::make_unique<LogToJournal>(severity));
break;
}
case TriggerAction::LogToRedfishEventLog:
{
actionsIf.emplace_back(
std::make_unique<LogToRedfishEventLog>());
break;
}
case TriggerAction::UpdateReport:
{
actionsIf.emplace_back(
std::make_unique<UpdateReport>(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<phosphor::logging::level::INFO>(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<phosphor::logging::level::INFO>(
"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<std::unique_ptr<interfaces::TriggerAction>>& actionsIf,
const std::vector<TriggerAction>& ActionsEnum, boost::asio::io_context& ioc,
const std::shared_ptr<std::vector<std::string>>& reportIds)
{
actionsIf.reserve(ActionsEnum.size());
for (auto actionType : ActionsEnum)
{
switch (actionType)
{
case TriggerAction::LogToJournal:
{
actionsIf.emplace_back(std::make_unique<LogToJournal>());
break;
}
case TriggerAction::LogToRedfishEventLog:
{
actionsIf.emplace_back(
std::make_unique<LogToRedfishEventLog>());
break;
}
case TriggerAction::UpdateReport:
{
actionsIf.emplace_back(
std::make_unique<UpdateReport>(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