1 #include "lg2_commit.hpp" 2 3 #include <sys/syslog.h> 4 5 #include <nlohmann/json.hpp> 6 #include <phosphor-logging/lg2/commit.hpp> 7 #include <sdbusplus/async.hpp> 8 #include <sdbusplus/exception.hpp> 9 #include <xyz/openbmc_project/Logging/Create/client.hpp> 10 #include <xyz/openbmc_project/Logging/Entry/client.hpp> 11 12 namespace lg2::details 13 { 14 15 using Create = sdbusplus::client::xyz::openbmc_project::logging::Create<>; 16 using Entry = sdbusplus::client::xyz::openbmc_project::logging::Entry<>; 17 18 /* Convert syslog severity to Entry::Level */ 19 static auto severity_from_syslog(int s) -> Entry::Level 20 { 21 switch (s) 22 { 23 case LOG_DEBUG: 24 return Entry::Level::Debug; 25 26 case LOG_INFO: 27 return Entry::Level::Informational; 28 29 case LOG_NOTICE: 30 return Entry::Level::Notice; 31 32 case LOG_WARNING: 33 return Entry::Level::Warning; 34 35 case LOG_ERR: 36 return Entry::Level::Error; 37 38 case LOG_CRIT: 39 return Entry::Level::Critical; 40 41 case LOG_ALERT: 42 return Entry::Level::Alert; 43 44 case LOG_EMERG: 45 return Entry::Level::Emergency; 46 } 47 return Entry::Level::Emergency; 48 } 49 50 using AdditionalData_t = std::map<std::string, std::string>; 51 52 /* Create AdditionalData from the sdbusplus event json. */ 53 static auto data_from_json(sdbusplus::exception::generated_event_base& t) 54 -> AdditionalData_t 55 { 56 AdditionalData_t result{}; 57 58 auto j = t.to_json()[t.name()]; 59 for (const auto& item : j.items()) 60 { 61 // Special cases for the "_SOURCE" fields, which contain debug 62 // information about the origin of the event. 63 if (item.key() == "_SOURCE") 64 { 65 for (const auto& source_item : item.value().items()) 66 { 67 if (source_item.key() == "PID") 68 { 69 result.emplace("_PID", source_item.value().dump()); 70 continue; 71 } 72 if (source_item.key() == "FILE") 73 { 74 result.emplace("_CODE_FILE", source_item.value()); 75 continue; 76 } 77 if (source_item.key() == "FUNCTION") 78 { 79 result.emplace("_CODE_FUNC", source_item.value()); 80 continue; 81 } 82 if (source_item.key() == "LINE") 83 { 84 result.emplace("_CODE_LINE", source_item.value().dump()); 85 continue; 86 } 87 } 88 continue; 89 } 90 91 result.emplace(item.key(), item.value().dump()); 92 } 93 94 return result; 95 } 96 97 auto commit(sdbusplus::exception::generated_event_base&& t) 98 -> sdbusplus::message::object_path 99 { 100 auto b = sdbusplus::bus::new_default(); 101 auto m = b.new_method_call(Create::default_service, Create::instance_path, 102 Create::interface, "Create"); 103 104 m.append(t.name(), severity_from_syslog(t.severity()), data_from_json(t)); 105 106 auto reply = b.call(m); 107 108 return reply.unpack<sdbusplus::message::object_path>(); 109 } 110 111 auto commit(sdbusplus::async::context& ctx, 112 sdbusplus::exception::generated_event_base&& t) 113 -> sdbusplus::async::task<sdbusplus::message::object_path> 114 { 115 co_return co_await Create(ctx) 116 .service(Create::default_service) 117 .path(Create::instance_path) 118 .create(t.name(), severity_from_syslog(t.severity()), 119 data_from_json(t)); 120 } 121 122 auto extractEvent(sdbusplus::exception::generated_event_base&& t) 123 -> std::tuple<std::string, Entry::Level, std::vector<std::string>> 124 { 125 auto data = data_from_json(t); 126 std::vector<std::string> additional_data = {}; 127 128 for (auto& [key, data] : data) 129 { 130 additional_data.emplace_back(key + "=" + data); 131 } 132 133 return {t.name(), severity_from_syslog(t.severity()), 134 std::move(additional_data)}; 135 } 136 137 } // namespace lg2::details 138