blob: c8404223616b28ed72dd3dcf6c62f786b7b708b6 [file] [log] [blame]
#include "trigger_actions.hpp"
#include "messages/update_report_ind.hpp"
#include "types/trigger_types.hpp"
#include "utils/messanger.hpp"
#include <phosphor-logging/log.hpp>
#include <ctime>
namespace action
{
namespace
{
std::string timestampToString(Milliseconds timestamp)
{
std::time_t t = static_cast<time_t>(timestamp.count());
std::array<char, sizeof("YYYY-MM-DDThh:mm:ssZ")> 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<phosphor::logging::level::INFO>(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<phosphor::logging::level::INFO>(
"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<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::LogToLogService:
{
actionsIf.emplace_back(
std::make_unique<LogToJournal>(type, thresholdValue));
break;
}
case TriggerAction::RedfishEvent:
{
actionsIf.emplace_back(
std::make_unique<LogToRedfish>(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& 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<phosphor::logging::level::INFO>(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<phosphor::logging::level::INFO>(
"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<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::LogToLogService:
{
actionsIf.emplace_back(
std::make_unique<LogToJournal>(severity));
break;
}
case TriggerAction::RedfishEvent:
{
actionsIf.emplace_back(
std::make_unique<LogToRedfish>(severity));
break;
}
case TriggerAction::UpdateReport:
{
actionsIf.emplace_back(
std::make_unique<UpdateReport>(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<phosphor::logging::level::INFO>(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<phosphor::logging::level::INFO>(
"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<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::LogToLogService:
{
actionsIf.emplace_back(std::make_unique<LogToJournal>());
break;
}
case TriggerAction::RedfishEvent:
{
actionsIf.emplace_back(std::make_unique<LogToRedfish>());
break;
}
case TriggerAction::UpdateReport:
{
actionsIf.emplace_back(
std::make_unique<UpdateReport>(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