1 #include <phosphor-logging/log.hpp> 2 #include <phosphor-logging/elog-errors.hpp> 3 #include <sdbusplus/server/manager.hpp> 4 #include <sdeventplus/event.hpp> 5 #include <sdbusplus/exception.hpp> 6 #include <systemd_target_signal.hpp> 7 #include <xyz/openbmc_project/Common/error.hpp> 8 9 namespace phosphor 10 { 11 namespace state 12 { 13 namespace manager 14 { 15 16 using phosphor::logging::elog; 17 using phosphor::logging::entry; 18 using phosphor::logging::level; 19 using phosphor::logging::log; 20 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 21 22 void SystemdTargetLogging::logError(const std::string& error, 23 const std::string& result) 24 { 25 auto method = this->bus.new_method_call( 26 "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging", 27 "xyz.openbmc_project.Logging.Create", "Create"); 28 // Signature is ssa{ss} 29 method.append(error); 30 method.append("xyz.openbmc_project.Logging.Entry.Level.Critical"); 31 method.append(std::array<std::pair<std::string, std::string>, 1>( 32 {std::pair<std::string, std::string>({"SYSTEMD_RESULT", result})})); 33 try 34 { 35 this->bus.call_noreply(method); 36 } 37 catch (const sdbusplus::exception::SdBusError& e) 38 { 39 log<level::ERR>("Failed to create systemd target error", 40 entry("ERROR=%s", error.c_str()), 41 entry("RESULT=%s", result.c_str()), 42 entry("SDBUSERR=%s", e.what())); 43 } 44 } 45 46 const std::string* SystemdTargetLogging::processError(const std::string& unit, 47 const std::string& result) 48 { 49 auto targetEntry = this->targetData.find(unit); 50 if (targetEntry != this->targetData.end()) 51 { 52 // Check if its result matches any of our monitored errors 53 if (std::find(targetEntry->second.errorsToMonitor.begin(), 54 targetEntry->second.errorsToMonitor.end(), 55 result) != targetEntry->second.errorsToMonitor.end()) 56 { 57 log<level::INFO>("Monitored systemd unit has hit an error", 58 entry("UNIT=%s", unit.c_str()), 59 entry("RESULT=%s", result.c_str())); 60 return (&targetEntry->second.errorToLog); 61 } 62 } 63 return {nullptr}; 64 } 65 66 void SystemdTargetLogging::systemdUnitChange(sdbusplus::message::message& msg) 67 { 68 uint32_t id; 69 sdbusplus::message::object_path objPath; 70 std::string unit{}; 71 std::string result{}; 72 73 msg.read(id, objPath, unit, result); 74 75 // In most cases it will just be success, in which case just return 76 if (result != "done") 77 { 78 const std::string* error = processError(unit, result); 79 80 // If this is a monitored error then log it 81 if (error) 82 { 83 logError(*error, result); 84 } 85 } 86 return; 87 } 88 89 void SystemdTargetLogging::subscribeToSystemdSignals() 90 { 91 auto method = this->bus.new_method_call( 92 "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 93 "org.freedesktop.systemd1.Manager", "Subscribe"); 94 95 try 96 { 97 this->bus.call(method); 98 } 99 catch (const sdbusplus::exception::SdBusError& e) 100 { 101 log<level::ERR>("Failed to subscribe to systemd signals", 102 entry("SDBUSERR=%s", e.what())); 103 elog<InternalFailure>(); 104 } 105 106 return; 107 } 108 109 } // namespace manager 110 } // namespace state 111 } // namespace phosphor 112