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