From 53e943637f690b071994e97b4a6501fb50dc7117 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Wed, 3 Jul 2024 15:08:21 +0000 Subject: [PATCH] Additional local changes Signed-off-by: Michael Carroll --- include/gz/common/ConsoleNew.hh | 38 ++++++++++++++++++++++++++---- src/ConsoleNew.cc | 41 +++++++++++++++++++++++++-------- src/ConsoleNew_TEST.cc | 38 ++++++++++++++++++++++-------- 3 files changed, 95 insertions(+), 22 deletions(-) diff --git a/include/gz/common/ConsoleNew.hh b/include/gz/common/ConsoleNew.hh index 75df9149..b70e4715 100644 --- a/include/gz/common/ConsoleNew.hh +++ b/include/gz/common/ConsoleNew.hh @@ -27,8 +27,10 @@ #include #include #include +#include "gz/common/Filesystem.hh" #include +#include namespace gz::common { @@ -42,9 +44,15 @@ namespace gz::common /// \brief Set the console output color mode public: void set_color_mode(spdlog::color_mode mode); + /// \brief Set the log destnation filename + public: void set_log_destination(const std::string &filename); + /// \brief Access the underlying spdlog logger public: [[nodiscard]] spdlog::logger& Logger() const; + /// \brief Access the underlying spdlog logger, with ownership + public: [[nodiscard]] std::shared_ptr LoggerPtr() const; + /// \brief Access the global gz console logger public: static ConsoleNew& Root(); @@ -73,12 +81,9 @@ namespace gz::common /// \brief Underlying stream private: std::ostringstream ss; }; - - - } // namespace gz::common -#define gzcrit (gz::common::LogMessage(__FILE__, __LINE__, spdlog::level::critical).stream()) +#define gzcrit gz::common::LogMessage(__FILE__, __LINE__, spdlog::level::critical).stream() #define gzerr gz::common::LogMessage(__FILE__, __LINE__, spdlog::level::err).stream() #define gzwarn gz::common::LogMessage(__FILE__, __LINE__, spdlog::level::warn).stream() #define gzlog gz::common::LogMessage(__FILE__, __LINE__, spdlog::level::info).stream() @@ -86,4 +91,29 @@ namespace gz::common #define gzdbg gz::common::LogMessage(__FILE__, __LINE__, spdlog::level::debug).stream() #define gztrace gz::common::LogMessage(__FILE__, __LINE__, spdlog::level::trace).stream() +void gzLogInit(const std::string &directory, const std::string &filename) +{ + auto &root = gz::common::ConsoleNew::Root(); + + std::string logPath; + if (!directory.empty()) + { + logPath = directory; + } else if(!gz::common::env(GZ_HOMEDIR, logPath)) { + root.Logger().error("Missing HOME environment variable. No log file will be generated."); + return; + } + + if(!gz::common::createDirectories(logPath)) + { + root.Logger().error("Failed to create output log directory {}", logPath.c_str()); + return; + } + + logPath = gz::common::joinPaths(logPath, filename); + root.Logger().info("Setting log file output destination to {}", logPath.c_str()); + gz::common::ConsoleNew::Root().set_log_destination(logPath); + spdlog::set_default_logger(root.LoggerPtr()); +} + #endif // GZ_COMMON_CONSOLENEW_HH_ diff --git a/src/ConsoleNew.cc b/src/ConsoleNew.cc index 7c3c3a02..94c3699c 100644 --- a/src/ConsoleNew.cc +++ b/src/ConsoleNew.cc @@ -26,8 +26,10 @@ #include #include #include +#include namespace { +/// \brief Custom log sink that routes to stdout/stderr in Gazebo conventions class gz_split_sink : public spdlog::sinks::sink { public: ~gz_split_sink() override = default; @@ -94,26 +96,32 @@ std::ostream& LogMessage::stream() class ConsoleNew::Implementation { public: - std::shared_ptr console_sink {nullptr}; + explicit Implementation(const std::string &logger_name): + console_sink(std::make_shared()), + sinks(std::make_shared()), + logger(std::make_shared(logger_name, sinks)) + { + } + + std::shared_ptr console_sink; std::shared_ptr file_sink {nullptr}; + std::shared_ptr sinks {nullptr}; + std::shared_ptr logger {nullptr}; }; ConsoleNew::ConsoleNew(const std::string &logger_name): - dataPtr(gz::utils::MakeUniqueImpl()) + dataPtr(gz::utils::MakeUniqueImpl(logger_name)) { - this->dataPtr->console_sink = std::make_shared(); - this->dataPtr->file_sink = std::make_shared("/tmp/filename.txt", true); - this->dataPtr->logger = std::make_shared(spdlog::logger(logger_name, - { - this->dataPtr->file_sink, this->dataPtr->console_sink - })); + // Add the console sink as a destination + this->dataPtr->sinks->add_sink(this->dataPtr->console_sink); // Configure the logger - this->dataPtr->logger->set_level(spdlog::level::trace); + this->dataPtr->logger->set_level(spdlog::level::info); this->dataPtr->logger->flush_on(spdlog::level::err); + spdlog::flush_every(std::chrono::seconds(5)); spdlog::register_logger(this->dataPtr->logger); } @@ -123,11 +131,26 @@ void ConsoleNew::set_color_mode(spdlog::color_mode mode) this->dataPtr->console_sink->set_color_mode(mode); } +void ConsoleNew::set_log_destination(const std::string &filename) +{ + if (this->dataPtr->file_sink != nullptr) + { + this->dataPtr->sinks->remove_sink(this->dataPtr->file_sink); + } + this->dataPtr->file_sink = std::make_shared(filename, true); + this->dataPtr->sinks->add_sink(this->dataPtr->file_sink); +} + spdlog::logger& ConsoleNew::Logger() const { return *this->dataPtr->logger; } +std::shared_ptr ConsoleNew::LoggerPtr() const +{ + return this->dataPtr->logger; +} + ConsoleNew& ConsoleNew::Root() { static gz::utils::NeverDestroyed root{"gz"}; diff --git a/src/ConsoleNew_TEST.cc b/src/ConsoleNew_TEST.cc index c59301d0..62f80460 100644 --- a/src/ConsoleNew_TEST.cc +++ b/src/ConsoleNew_TEST.cc @@ -24,16 +24,16 @@ #include class ConsoleNew_TEST : public ::testing::Test { - protected: virtual void SetUp() + protected: void SetUp() override { this->temp = std::make_unique( - "test", "gz_common", true); + "test", "gz_common", false); ASSERT_TRUE(this->temp->Valid()); gz::common::setenv(GZ_HOMEDIR, this->temp->Path()); } /// \brief Clear out all the directories we produced during this test. - public: virtual void TearDown() + public: void TearDown() override { EXPECT_TRUE(gz::common::unsetenv(GZ_HOMEDIR)); } @@ -89,10 +89,30 @@ TEST_F(ConsoleNew_TEST, RootLoggerNoColor) TEST_F(ConsoleNew_TEST, RootLoggerMacros) { - gztrace << "This is a trace message"; - gzdbg << "This is a debug message"; - gzmsg << "This is an info message"; - gzwarn << "This is a warning message"; - gzerr << "This is an error message"; - gzcrit << "This is a critical message"; + gztrace << "This is a trace message"; + gzdbg << "This is a debug message"; + gzmsg << "This is an info message"; + gzwarn << "This is a warning message"; + gzerr << "This is an error message"; + gzcrit << "This is a critical message"; +} + +TEST_F(ConsoleNew_TEST, LogToFile) +{ + gzLogInit("", "test.log"); + + gztrace << "This is a trace message"; + gzdbg << "This is a debug message"; + gzmsg << "This is an info message"; + gzwarn << "This is a warning message"; + gzerr << "This is an error message"; + gzcrit << "This is a critical message"; + + // gzLogInit installs a global handler + spdlog::trace("This is a trace message"); + spdlog::debug("This is a debug message"); + spdlog::info("This is an info message"); + spdlog::warn("This is a warning message"); + spdlog::error("This is an error message"); + spdlog::critical("This is a critical message"); }