1 #include <cereal/cereal.hpp> 2 #include <phosphor-logging/elog.hpp> 3 4 #include "elog_watch.hpp" 5 #include "dump_internal.hpp" 6 #include "xyz/openbmc_project/Dump/Create/error.hpp" 7 #include "dump_serialize.hpp" 8 #include "config.h" 9 10 // Register class version with Cereal 11 CEREAL_CLASS_VERSION(phosphor::dump::elog::Watch, CLASS_VERSION); 12 13 namespace phosphor 14 { 15 namespace dump 16 { 17 namespace elog 18 { 19 20 using namespace phosphor::logging; 21 constexpr auto LOG_PATH = "/xyz/openbmc_project/logging"; 22 constexpr auto INTERNAL_FAILURE = 23 "xyz.openbmc_project.Common.Error.InternalFailure"; 24 using Message = std::string; 25 using Attributes = sdbusplus::message::variant<Message>; 26 using AttributeName = std::string; 27 using AttributeMap = std::map<AttributeName, Attributes>; 28 using PropertyName = std::string; 29 using PropertyMap = std::map<PropertyName, AttributeMap>; 30 using LogEntryMsg = std::pair<sdbusplus::message::object_path, PropertyMap>; 31 32 Watch::Watch(sdbusplus::bus::bus& bus, IMgr& iMgr): 33 iMgr(iMgr), 34 addMatch( 35 bus, 36 sdbusplus::bus::match::rules::interfacesAdded() + 37 sdbusplus::bus::match::rules::path_namespace( 38 OBJ_LOGGING), 39 std::bind(std::mem_fn(&Watch::addCallback), 40 this, std::placeholders::_1)), 41 delMatch( 42 bus, 43 sdbusplus::bus::match::rules::interfacesRemoved() + 44 sdbusplus::bus::match::rules::path_namespace( 45 OBJ_LOGGING), 46 std::bind(std::mem_fn(&Watch::delCallback), 47 this, std::placeholders::_1)) 48 { 49 50 fs::path file(ELOG_ID_PERSIST_PATH); 51 if (fs::exists(file)) 52 { 53 if (!deserialize(ELOG_ID_PERSIST_PATH, elogList)) 54 { 55 log<level::ERR>("Error occurred during error id deserialize"); 56 } 57 } 58 } 59 60 void Watch::addCallback(sdbusplus::message::message& msg) 61 { 62 using Type = 63 sdbusplus::xyz::openbmc_project::Dump::Internal::server::Create::Type; 64 using QuotaExceeded = 65 sdbusplus::xyz::openbmc_project::Dump::Create::Error::QuotaExceeded; 66 67 LogEntryMsg logEntry; 68 msg.read(logEntry); 69 70 std::string objectPath(std::move(logEntry.first)); 71 72 std::size_t found = objectPath.find("entry"); 73 if (found == std::string::npos) 74 { 75 //Not a new error entry skip 76 return; 77 } 78 79 auto eId = getEid(objectPath); 80 81 auto search = elogList.find(eId); 82 if (search != elogList.end()) 83 { 84 //elog exists in the list, Skip the dump 85 return; 86 } 87 88 auto iter = logEntry.second.find("xyz.openbmc_project.Logging.Entry"); 89 if (iter == logEntry.second.end()) 90 { 91 return; 92 } 93 94 auto attr = iter->second.find("Message"); 95 if (attr == iter->second.end()) 96 { 97 return; 98 } 99 100 auto& data = 101 sdbusplus::message::variant_ns::get<PropertyName>(attr->second); 102 if (data.empty()) 103 { 104 //No Message skip 105 return; 106 } 107 108 if (data != INTERNAL_FAILURE) 109 { 110 //Not a InternalFailure, skip 111 return; 112 } 113 114 std::vector<std::string> fullPaths; 115 fullPaths.push_back(objectPath); 116 117 try 118 { 119 //Save the elog information. This is to avoid dump requests 120 //in elog restore path. 121 elogList.insert(eId); 122 123 phosphor::dump::elog::serialize(elogList); 124 125 //Call internal create function to initiate dump 126 iMgr.IMgr::create(Type::InternalFailure, fullPaths); 127 } 128 catch (QuotaExceeded& e) 129 { 130 //No action now 131 } 132 return; 133 } 134 135 void Watch::delCallback(sdbusplus::message::message& msg) 136 { 137 sdbusplus::message::object_path logEntry; 138 msg.read(logEntry); 139 140 //Get elog entry message string. 141 std::string objectPath(logEntry); 142 143 //Get elog id 144 auto eId = getEid(objectPath); 145 146 //Delete the elog entry from the list and serialize 147 auto search = elogList.find(eId); 148 if (search != elogList.end()) 149 { 150 elogList.erase(search); 151 phosphor::dump::elog::serialize(elogList); 152 } 153 } 154 155 }//namespace elog 156 }//namespace dump 157 }//namespace phosphor 158