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