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