1b26ff34dSEd Tanous #include "dbus_log_watcher.hpp" 2b26ff34dSEd Tanous 32ac69850SEd Tanous #include "dbus_singleton.hpp" 4b26ff34dSEd Tanous #include "dbus_utility.hpp" 56c58a03eSAlexander Hansen #include "event_logs_object_type.hpp" 6b26ff34dSEd Tanous #include "event_service_manager.hpp" 7b26ff34dSEd Tanous #include "logging.hpp" 8b26ff34dSEd Tanous #include "metric_report.hpp" 96c58a03eSAlexander Hansen #include "utils/dbus_event_log_entry.hpp" 104a7a15c2SAlexander Hansen #include "utils/time_utils.hpp" 11b26ff34dSEd Tanous 122ac69850SEd Tanous #include <sdbusplus/bus/match.hpp> 13b26ff34dSEd Tanous #include <sdbusplus/message.hpp> 14b26ff34dSEd Tanous #include <sdbusplus/message/native_types.hpp> 15b26ff34dSEd Tanous 16b26ff34dSEd Tanous #include <algorithm> 176c58a03eSAlexander Hansen #include <optional> 18b26ff34dSEd Tanous #include <string> 19b26ff34dSEd Tanous #include <variant> 20b26ff34dSEd Tanous #include <vector> 21b26ff34dSEd Tanous 22b26ff34dSEd Tanous namespace redfish 23b26ff34dSEd Tanous { 244a7a15c2SAlexander Hansen 25*56431b29SAlexander Hansen bool DbusEventLogMonitor::eventLogObjectFromDBus( 26*56431b29SAlexander Hansen const dbus::utility::DBusPropertiesMap& map, EventLogObjectsType& event) 276c58a03eSAlexander Hansen { 286c58a03eSAlexander Hansen std::optional<DbusEventLogEntry> optEntry = 296c58a03eSAlexander Hansen fillDbusEventLogEntryFromPropertyMap(map); 306c58a03eSAlexander Hansen 316c58a03eSAlexander Hansen if (!optEntry.has_value()) 326c58a03eSAlexander Hansen { 336c58a03eSAlexander Hansen BMCWEB_LOG_ERROR( 346c58a03eSAlexander Hansen "Could not construct event log entry from dbus properties"); 356c58a03eSAlexander Hansen return false; 366c58a03eSAlexander Hansen } 376c58a03eSAlexander Hansen DbusEventLogEntry& entry = optEntry.value(); 386c58a03eSAlexander Hansen event.id = std::to_string(entry.Id); 394a7a15c2SAlexander Hansen event.timestamp = redfish::time_utils::getDateTimeUintMs(entry.Timestamp); 406c58a03eSAlexander Hansen 41546d0785SAlexander Hansen // This dbus property is not documented to contain the Redfish Message Id, 42546d0785SAlexander Hansen // but can be used as such. As a temporary solution that is sufficient, 43546d0785SAlexander Hansen // the event filtering code will drop the event anyways if event.messageId 44546d0785SAlexander Hansen // is not valid. 45546d0785SAlexander Hansen // 46546d0785SAlexander Hansen // This will need resolved before 47546d0785SAlexander Hansen // experimental-redfish-dbus-log-subscription is stabilized 48546d0785SAlexander Hansen event.messageId = entry.Message; 49546d0785SAlexander Hansen 506c58a03eSAlexander Hansen // The order of 'AdditionalData' is not what's specified in an e.g. 516c58a03eSAlexander Hansen // busctl call to create the Event Log Entry. So it cannot be used 526c58a03eSAlexander Hansen // to map to the message args. Leaving this branch here for it to be 536c58a03eSAlexander Hansen // implemented when the mapping is available 546c58a03eSAlexander Hansen 556c58a03eSAlexander Hansen return true; 566c58a03eSAlexander Hansen } 576c58a03eSAlexander Hansen 586c58a03eSAlexander Hansen static void dbusEventLogMatchHandlerSingleEntry( 596c58a03eSAlexander Hansen const dbus::utility::DBusPropertiesMap& map) 606c58a03eSAlexander Hansen { 616c58a03eSAlexander Hansen std::vector<EventLogObjectsType> eventRecords; 626c58a03eSAlexander Hansen EventLogObjectsType& event = eventRecords.emplace_back(); 63*56431b29SAlexander Hansen bool success = DbusEventLogMonitor::eventLogObjectFromDBus(map, event); 646c58a03eSAlexander Hansen if (!success) 656c58a03eSAlexander Hansen { 666c58a03eSAlexander Hansen BMCWEB_LOG_ERROR("Could not parse event log entry from dbus"); 676c58a03eSAlexander Hansen return; 686c58a03eSAlexander Hansen } 696c58a03eSAlexander Hansen 706c58a03eSAlexander Hansen BMCWEB_LOG_DEBUG("Found Event Log Entry Id={}, Timestamp={}, Message={}", 716c58a03eSAlexander Hansen event.id, event.timestamp, event.messageId); 726c58a03eSAlexander Hansen EventServiceManager::sendEventsToSubs(eventRecords); 736c58a03eSAlexander Hansen } 746c58a03eSAlexander Hansen 756c58a03eSAlexander Hansen static void onDbusEventLogCreated(sdbusplus::message_t& msg) 766c58a03eSAlexander Hansen { 776c58a03eSAlexander Hansen BMCWEB_LOG_DEBUG("Handling new DBus Event Log Entry"); 786c58a03eSAlexander Hansen 796c58a03eSAlexander Hansen sdbusplus::message::object_path objectPath; 806c58a03eSAlexander Hansen dbus::utility::DBusInterfacesMap interfaces; 816c58a03eSAlexander Hansen 826c58a03eSAlexander Hansen msg.read(objectPath, interfaces); 836c58a03eSAlexander Hansen 846c58a03eSAlexander Hansen for (auto& pair : interfaces) 856c58a03eSAlexander Hansen { 866c58a03eSAlexander Hansen BMCWEB_LOG_DEBUG("Found dbus interface {}", pair.first); 876c58a03eSAlexander Hansen if (pair.first == "xyz.openbmc_project.Logging.Entry") 886c58a03eSAlexander Hansen { 896c58a03eSAlexander Hansen const dbus::utility::DBusPropertiesMap& map = pair.second; 906c58a03eSAlexander Hansen dbusEventLogMatchHandlerSingleEntry(map); 916c58a03eSAlexander Hansen } 926c58a03eSAlexander Hansen } 936c58a03eSAlexander Hansen } 946c58a03eSAlexander Hansen 956c58a03eSAlexander Hansen const std::string propertiesMatchString = 966c58a03eSAlexander Hansen sdbusplus::bus::match::rules::type::signal() + 976c58a03eSAlexander Hansen sdbusplus::bus::match::rules::sender("xyz.openbmc_project.Logging") + 986c58a03eSAlexander Hansen sdbusplus::bus::match::rules::interface( 996c58a03eSAlexander Hansen "org.freedesktop.DBus.ObjectManager") + 1006c58a03eSAlexander Hansen sdbusplus::bus::match::rules::path("/xyz/openbmc_project/logging") + 1016c58a03eSAlexander Hansen sdbusplus::bus::match::rules::member("InterfacesAdded"); 1026c58a03eSAlexander Hansen 1036c58a03eSAlexander Hansen DbusEventLogMonitor::DbusEventLogMonitor() : 1046c58a03eSAlexander Hansen dbusEventLogMonitor(*crow::connections::systemBus, propertiesMatchString, 1056c58a03eSAlexander Hansen onDbusEventLogCreated) 1066c58a03eSAlexander Hansen 1076c58a03eSAlexander Hansen {} 1086c58a03eSAlexander Hansen 1092ac69850SEd Tanous static void getReadingsForReport(sdbusplus::message_t& msg) 110b26ff34dSEd Tanous { 111b26ff34dSEd Tanous if (msg.is_method_error()) 112b26ff34dSEd Tanous { 113b26ff34dSEd Tanous BMCWEB_LOG_ERROR("TelemetryMonitor Signal error"); 114b26ff34dSEd Tanous return; 115b26ff34dSEd Tanous } 116b26ff34dSEd Tanous 117b26ff34dSEd Tanous sdbusplus::message::object_path path(msg.get_path()); 118b26ff34dSEd Tanous std::string id = path.filename(); 119b26ff34dSEd Tanous if (id.empty()) 120b26ff34dSEd Tanous { 121b26ff34dSEd Tanous BMCWEB_LOG_ERROR("Failed to get Id from path"); 122b26ff34dSEd Tanous return; 123b26ff34dSEd Tanous } 124b26ff34dSEd Tanous 125b26ff34dSEd Tanous std::string interface; 126b26ff34dSEd Tanous dbus::utility::DBusPropertiesMap props; 127b26ff34dSEd Tanous std::vector<std::string> invalidProps; 128b26ff34dSEd Tanous msg.read(interface, props, invalidProps); 129b26ff34dSEd Tanous 130b26ff34dSEd Tanous auto found = std::ranges::find_if(props, [](const auto& x) { 131b26ff34dSEd Tanous return x.first == "Readings"; 132b26ff34dSEd Tanous }); 133b26ff34dSEd Tanous if (found == props.end()) 134b26ff34dSEd Tanous { 135b26ff34dSEd Tanous BMCWEB_LOG_INFO("Failed to get Readings from Report properties"); 136b26ff34dSEd Tanous return; 137b26ff34dSEd Tanous } 138b26ff34dSEd Tanous 139b26ff34dSEd Tanous const telemetry::TimestampReadings* readings = 140b26ff34dSEd Tanous std::get_if<telemetry::TimestampReadings>(&found->second); 141b26ff34dSEd Tanous if (readings == nullptr) 142b26ff34dSEd Tanous { 143b26ff34dSEd Tanous BMCWEB_LOG_INFO("Failed to get Readings from Report properties"); 144b26ff34dSEd Tanous return; 145b26ff34dSEd Tanous } 146b26ff34dSEd Tanous EventServiceManager::sendTelemetryReportToSubs(id, *readings); 147b26ff34dSEd Tanous } 1482ac69850SEd Tanous 1492ac69850SEd Tanous const std::string telemetryMatchStr = 1502ac69850SEd Tanous "type='signal',member='PropertiesChanged'," 1512ac69850SEd Tanous "interface='org.freedesktop.DBus.Properties'," 1522ac69850SEd Tanous "arg0=xyz.openbmc_project.Telemetry.Report"; 1532ac69850SEd Tanous 1542ac69850SEd Tanous DbusTelemetryMonitor::DbusTelemetryMonitor() : 1552ac69850SEd Tanous matchTelemetryMonitor(*crow::connections::systemBus, telemetryMatchStr, 1562ac69850SEd Tanous getReadingsForReport) 1572ac69850SEd Tanous {} 158b26ff34dSEd Tanous } // namespace redfish 159