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