1 #include "dbus_log_watcher.hpp"
2 
3 #include "dbus_singleton.hpp"
4 #include "dbus_utility.hpp"
5 #include "event_logs_object_type.hpp"
6 #include "event_service_manager.hpp"
7 #include "logging.hpp"
8 #include "metric_report.hpp"
9 #include "utils/dbus_event_log_entry.hpp"
10 
11 #include <sdbusplus/bus/match.hpp>
12 #include <sdbusplus/message.hpp>
13 #include <sdbusplus/message/native_types.hpp>
14 
15 #include <algorithm>
16 #include <optional>
17 #include <string>
18 #include <variant>
19 #include <vector>
20 
21 namespace redfish
22 {
eventLogObjectFromDBus(const dbus::utility::DBusPropertiesMap & map,EventLogObjectsType & event)23 static bool eventLogObjectFromDBus(const dbus::utility::DBusPropertiesMap& map,
24                                    EventLogObjectsType& event)
25 {
26     std::optional<DbusEventLogEntry> optEntry =
27         fillDbusEventLogEntryFromPropertyMap(map);
28 
29     if (!optEntry.has_value())
30     {
31         BMCWEB_LOG_ERROR(
32             "Could not construct event log entry from dbus properties");
33         return false;
34     }
35     DbusEventLogEntry& entry = optEntry.value();
36     event.id = std::to_string(entry.Id);
37 
38     // The order of 'AdditionalData' is not what's specified in an e.g.
39     // busctl call to create the Event Log Entry. So it cannot be used
40     // to map to the message args. Leaving this branch here for it to be
41     // implemented when the mapping is available
42 
43     return true;
44 }
45 
dbusEventLogMatchHandlerSingleEntry(const dbus::utility::DBusPropertiesMap & map)46 static void dbusEventLogMatchHandlerSingleEntry(
47     const dbus::utility::DBusPropertiesMap& map)
48 {
49     std::vector<EventLogObjectsType> eventRecords;
50     EventLogObjectsType& event = eventRecords.emplace_back();
51     bool success = eventLogObjectFromDBus(map, event);
52     if (!success)
53     {
54         BMCWEB_LOG_ERROR("Could not parse event log entry from dbus");
55         return;
56     }
57 
58     BMCWEB_LOG_DEBUG("Found Event Log Entry Id={}, Timestamp={}, Message={}",
59                      event.id, event.timestamp, event.messageId);
60     EventServiceManager::sendEventsToSubs(eventRecords);
61 }
62 
onDbusEventLogCreated(sdbusplus::message_t & msg)63 static void onDbusEventLogCreated(sdbusplus::message_t& msg)
64 {
65     BMCWEB_LOG_DEBUG("Handling new DBus Event Log Entry");
66 
67     sdbusplus::message::object_path objectPath;
68     dbus::utility::DBusInterfacesMap interfaces;
69 
70     msg.read(objectPath, interfaces);
71 
72     for (auto& pair : interfaces)
73     {
74         BMCWEB_LOG_DEBUG("Found dbus interface {}", pair.first);
75         if (pair.first == "xyz.openbmc_project.Logging.Entry")
76         {
77             const dbus::utility::DBusPropertiesMap& map = pair.second;
78             dbusEventLogMatchHandlerSingleEntry(map);
79         }
80     }
81 }
82 
83 const std::string propertiesMatchString =
84     sdbusplus::bus::match::rules::type::signal() +
85     sdbusplus::bus::match::rules::sender("xyz.openbmc_project.Logging") +
86     sdbusplus::bus::match::rules::interface(
87         "org.freedesktop.DBus.ObjectManager") +
88     sdbusplus::bus::match::rules::path("/xyz/openbmc_project/logging") +
89     sdbusplus::bus::match::rules::member("InterfacesAdded");
90 
DbusEventLogMonitor()91 DbusEventLogMonitor::DbusEventLogMonitor() :
92     dbusEventLogMonitor(*crow::connections::systemBus, propertiesMatchString,
93                         onDbusEventLogCreated)
94 
95 {}
96 
getReadingsForReport(sdbusplus::message_t & msg)97 static void getReadingsForReport(sdbusplus::message_t& msg)
98 {
99     if (msg.is_method_error())
100     {
101         BMCWEB_LOG_ERROR("TelemetryMonitor Signal error");
102         return;
103     }
104 
105     sdbusplus::message::object_path path(msg.get_path());
106     std::string id = path.filename();
107     if (id.empty())
108     {
109         BMCWEB_LOG_ERROR("Failed to get Id from path");
110         return;
111     }
112 
113     std::string interface;
114     dbus::utility::DBusPropertiesMap props;
115     std::vector<std::string> invalidProps;
116     msg.read(interface, props, invalidProps);
117 
118     auto found = std::ranges::find_if(props, [](const auto& x) {
119         return x.first == "Readings";
120     });
121     if (found == props.end())
122     {
123         BMCWEB_LOG_INFO("Failed to get Readings from Report properties");
124         return;
125     }
126 
127     const telemetry::TimestampReadings* readings =
128         std::get_if<telemetry::TimestampReadings>(&found->second);
129     if (readings == nullptr)
130     {
131         BMCWEB_LOG_INFO("Failed to get Readings from Report properties");
132         return;
133     }
134     EventServiceManager::sendTelemetryReportToSubs(id, *readings);
135 }
136 
137 const std::string telemetryMatchStr =
138     "type='signal',member='PropertiesChanged',"
139     "interface='org.freedesktop.DBus.Properties',"
140     "arg0=xyz.openbmc_project.Telemetry.Report";
141 
DbusTelemetryMonitor()142 DbusTelemetryMonitor::DbusTelemetryMonitor() :
143     matchTelemetryMonitor(*crow::connections::systemBus, telemetryMatchStr,
144                           getReadingsForReport)
145 {}
146 } // namespace redfish
147