blob: 009a9d0f51597b0313db662bbae6e56b751d7e90 [file] [log] [blame]
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <sdbusplus/server/manager.hpp>
#include <sdeventplus/event.hpp>
#include <sdbusplus/exception.hpp>
#include <systemd_target_signal.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
namespace phosphor
{
namespace state
{
namespace manager
{
using phosphor::logging::elog;
using phosphor::logging::entry;
using phosphor::logging::level;
using phosphor::logging::log;
using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
void SystemdTargetLogging::logError(const std::string& error,
const std::string& result)
{
auto method = this->bus.new_method_call(
"xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
"xyz.openbmc_project.Logging.Create", "Create");
// Signature is ssa{ss}
method.append(error);
method.append("xyz.openbmc_project.Logging.Entry.Level.Critical");
method.append(std::array<std::pair<std::string, std::string>, 1>(
{std::pair<std::string, std::string>({"SYSTEMD_RESULT", result})}));
try
{
this->bus.call_noreply(method);
}
catch (const sdbusplus::exception::SdBusError& e)
{
log<level::ERR>("Failed to create systemd target error",
entry("ERROR=%s", error.c_str()),
entry("RESULT=%s", result.c_str()),
entry("SDBUSERR=%s", e.what()));
}
}
const std::string* SystemdTargetLogging::processError(const std::string& unit,
const std::string& result)
{
auto targetEntry = this->targetData.find(unit);
if (targetEntry != this->targetData.end())
{
// Check if its result matches any of our monitored errors
if (std::find(targetEntry->second.errorsToMonitor.begin(),
targetEntry->second.errorsToMonitor.end(),
result) != targetEntry->second.errorsToMonitor.end())
{
log<level::INFO>("Monitored systemd unit has hit an error",
entry("UNIT=%s", unit.c_str()),
entry("RESULT=%s", result.c_str()));
return (&targetEntry->second.errorToLog);
}
}
return {nullptr};
}
void SystemdTargetLogging::systemdUnitChange(sdbusplus::message::message& msg)
{
uint32_t id;
sdbusplus::message::object_path objPath;
std::string unit{};
std::string result{};
msg.read(id, objPath, unit, result);
// In most cases it will just be success, in which case just return
if (result != "done")
{
const std::string* error = processError(unit, result);
// If this is a monitored error then log it
if (error)
{
logError(*error, result);
}
}
return;
}
void SystemdTargetLogging::subscribeToSystemdSignals()
{
auto method = this->bus.new_method_call(
"org.freedesktop.systemd1", "/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager", "Subscribe");
try
{
this->bus.call(method);
}
catch (const sdbusplus::exception::SdBusError& e)
{
log<level::ERR>("Failed to subscribe to systemd signals",
entry("SDBUSERR=%s", e.what()));
elog<InternalFailure>();
}
return;
}
} // namespace manager
} // namespace state
} // namespace phosphor