Last active
January 19, 2023 12:18
-
-
Save jwpleow/88dac73d7e841ab7eb26f1364828e006 to your computer and use it in GitHub Desktop.
test ipc logging using iceoryx and spdlog
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| cmake_minimum_required(VERSION 3.15) | |
| include_guard(GLOBAL) | |
| project(ipc_logging) | |
| find_package(spdlog CONFIG REQUIRED) | |
| find_package(iceoryx_posh CONFIG REQUIRED) | |
| find_package(iceoryx_hoofs CONFIG REQUIRED) | |
| include(GNUInstallDirs) | |
| add_library(ipc_logging INTERFACE) | |
| add_library(waffle::ipc_logging ALIAS ipc_logging) | |
| target_include_directories(ipc_logging | |
| INTERFACE | |
| $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}> | |
| $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> | |
| ) | |
| target_link_libraries(ipc_logging | |
| INTERFACE | |
| spdlog::spdlog | |
| iceoryx_posh::iceoryx_posh | |
| iceoryx_hoofs::iceoryx_hoofs | |
| ) | |
| target_compile_features(ipc_logging PUBLIC cxx_std_11) | |
| install(FILES subscriber.hpp spdlog_ipc_sink.hpp | |
| DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <iceoryx_posh/popo/untyped_publisher.hpp> | |
| #include <spdlog/sinks/base_sink.h> | |
| #include <spdlog/spdlog.h> | |
| namespace waffle | |
| { | |
| // The iceoryx runtime MUST be initialised before instantiating this. | |
| template<typename Mutex> | |
| class iceoryx_sink : public spdlog::sinks::base_sink<Mutex> | |
| { | |
| public: | |
| // Make sure the ID's are <100 characters! | |
| iceoryx_sink(const std::string& serviceID, | |
| const std::string& instanceID, | |
| const std::string& eventID) | |
| : m_publisher(iox::capro::ServiceDescription(iox::capro::IdString_t(iox::cxx::TruncateToCapacity, serviceID), | |
| iox::capro::IdString_t(iox::cxx::TruncateToCapacity, instanceID), | |
| iox::capro::IdString_t(iox::cxx::TruncateToCapacity, eventID)), | |
| iox::popo::PublisherOptions{16U, "", true, iox::popo::ConsumerTooSlowPolicy::WAIT_FOR_CONSUMER} | |
| ) | |
| { | |
| } | |
| protected: | |
| void sink_it_(const spdlog::details::log_msg& msg) override | |
| { | |
| spdlog::memory_buf_t formatted; | |
| spdlog::sinks::base_sink<Mutex>::formatter_->format(msg, formatted); | |
| const auto logString = fmt::to_string(formatted); | |
| m_publisher.loan(logString.size() + 1) | |
| .and_then([&](auto& payload) { | |
| std::memcpy(reinterpret_cast<char*>(payload), logString.c_str(), logString.size() + 1); | |
| m_publisher.publish(payload); | |
| }) | |
| .or_else([&](auto& error) { | |
| std::cerr << "waffle::iceoryx_sink - Unable to loan memory for publish call. Error code " << static_cast<uint64_t>(error) << "\n"; | |
| }); | |
| } | |
| void flush_() override | |
| { | |
| } | |
| protected: | |
| iox::popo::UntypedPublisher m_publisher; | |
| }; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <string> | |
| #include <iceoryx_posh/popo/untyped_subscriber.hpp> | |
| #include <iceoryx_posh/popo/listener.hpp> | |
| #include <spdlog/spdlog.h> | |
| namespace waffle | |
| { | |
| // The iceoryx runtime MUST be initialised before instantiating this. | |
| template <class Queue> // e.g. https://github.com/cameron314/readerwriterqueue | |
| class LogSubscriber | |
| { | |
| public: | |
| LogSubscriber(const std::string& serviceID, | |
| const std::string& instanceID, | |
| const std::string& eventID, | |
| ); | |
| Queue& GetQueue() { return m_logQueue; } | |
| private: | |
| static void OnDataReceivedCallbackImpl(iox::popo::UntypedSubscriber* subscriber, LogSubscriber* self); | |
| private: | |
| iox::popo::Listener m_ioxListener; | |
| iox::popo::UntypedSubscriber m_subscriber; | |
| Queue m_logQueue{1024}; | |
| }; | |
| inline LogSubscriber::LogSubscriber(const std::string& serviceID, | |
| const std::string& instanceID, | |
| const std::string& eventID, | |
| LogCallbackFn callback | |
| ) | |
| : m_subscriber(iox::capro::ServiceDescription(iox::capro::IdString_t(iox::cxx::TruncateToCapacity, serviceID), | |
| iox::capro::IdString_t(iox::cxx::TruncateToCapacity, instanceID), | |
| iox::capro::IdString_t(iox::cxx::TruncateToCapacity, eventID)), | |
| iox::popo::SubscriberOptions{256U, 0, "", true, iox::popo::QueueFullPolicy::BLOCK_PRODUCER}) | |
| { | |
| m_ioxListener | |
| .attachEvent(m_subscriber, | |
| iox::popo::SubscriberEvent::DATA_RECEIVED, | |
| iox::popo::createNotificationCallback(OnDataReceivedCallbackImpl, *this)) | |
| .or_else([&](auto) { | |
| spdlog::error("LogSubscriber - Unable to attach the subscriber."); | |
| }); | |
| } | |
| inline void LogSubscriber::OnDataReceivedCallbackImpl(iox::popo::UntypedSubscriber* subscriber, LogSubscriber* self) | |
| { | |
| // Use a lock-free queue so we don't block the publisher as much as possible | |
| while(subscriber->take().and_then([subscriber, self](auto& payload) { | |
| std::string logString(reinterpret_cast<const char*>(payload)); // Rely on null-terminator | |
| self->m_logQueue.enqueue(std::move(logString)); | |
| subscriber->release(payload); | |
| })) {} | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment