From 2e4e85f1413485ede3e70fa84a97f8c9e4d5b1ea Mon Sep 17 00:00:00 2001 From: dhood Date: Mon, 4 Dec 2017 16:07:29 -0800 Subject: [PATCH] Add Logger class and give one to nodes (#411) * Add Logger class and give one to nodes * Try to improve compiler errors when non-Logger is passed to macros * Add define for 'disabling' loggers * Add/update tests * Linter fix * Documentation * Windows fix * Move free functions to source file (windows was upset) * Fix windows by changing prototype ordering * Store node logger in NodeBase * Windows is not happy with this EXPECT_ANY_THROW * Move get_logger to a NodeLogger interface * Move Logger into 'logger' namespace * Move helper function for macro errors into macro header * Remove 'logger' namespace * Return type on separate line * Update copyright year * Give lifecycle nodes a logger * Add test for lifecycle node logger Move the default_state_machine tests to another file because having different test fixtures was causing init to be called twice. * Switch to static_assert for logger check * global ns scope in macro calls just in case * Revert "Add test for lifecycle node logger" (make diff smaller) demos use the loggers and we don't test other node stuff in lifecycle_node * Update for rcutils function name change * Add reference to Node::get_logger() in doxygen * Rename NodeLoggerInterface to NodeLoggingInterface --- rclcpp/CMakeLists.txt | 5 + rclcpp/include/rclcpp/logger.hpp | 131 ++++++++++++++++++ rclcpp/include/rclcpp/node.hpp | 9 ++ .../rclcpp/node_interfaces/node_logging.hpp | 61 ++++++++ .../node_logging_interface.hpp | 47 +++++++ rclcpp/include/rclcpp/rclcpp.hpp | 23 +-- rclcpp/resource/logging.hpp.em | 14 +- rclcpp/src/rclcpp/logger.cpp | 33 +++++ rclcpp/src/rclcpp/node.cpp | 8 ++ .../rclcpp/node_interfaces/node_logging.cpp | 34 +++++ rclcpp/test/test_logger.cpp | 35 +++++ rclcpp/test/test_logging.cpp | 33 ++--- rclcpp/test/test_node.cpp | 12 ++ .../rclcpp_lifecycle/lifecycle_node.hpp | 9 ++ rclcpp_lifecycle/src/lifecycle_node.cpp | 9 ++ 15 files changed, 424 insertions(+), 39 deletions(-) create mode 100644 rclcpp/include/rclcpp/logger.hpp create mode 100644 rclcpp/include/rclcpp/node_interfaces/node_logging.hpp create mode 100644 rclcpp/include/rclcpp/node_interfaces/node_logging_interface.hpp create mode 100644 rclcpp/src/rclcpp/logger.cpp create mode 100644 rclcpp/src/rclcpp/node_interfaces/node_logging.cpp create mode 100644 rclcpp/test/test_logger.cpp diff --git a/rclcpp/CMakeLists.txt b/rclcpp/CMakeLists.txt index 357a96c..7190709 100644 --- a/rclcpp/CMakeLists.txt +++ b/rclcpp/CMakeLists.txt @@ -45,12 +45,14 @@ set(${PROJECT_NAME}_SRCS src/rclcpp/graph_listener.cpp src/rclcpp/intra_process_manager.cpp src/rclcpp/intra_process_manager_impl.cpp + src/rclcpp/logger.cpp src/rclcpp/memory_strategies.cpp src/rclcpp/memory_strategy.cpp src/rclcpp/node.cpp src/rclcpp/node_interfaces/node_base.cpp src/rclcpp/node_interfaces/node_clock.cpp src/rclcpp/node_interfaces/node_graph.cpp + src/rclcpp/node_interfaces/node_logging.cpp src/rclcpp/node_interfaces/node_parameters.cpp src/rclcpp/node_interfaces/node_services.cpp src/rclcpp/node_interfaces/node_timers.cpp @@ -297,6 +299,9 @@ if(BUILD_TESTING) target_link_libraries(test_executor ${PROJECT_NAME}) endif() + ament_add_gtest(test_logger test/test_logger.cpp) + target_link_libraries(test_logger ${PROJECT_NAME}) + ament_add_gmock(test_logging test/test_logging.cpp) target_link_libraries(test_logging ${PROJECT_NAME}) diff --git a/rclcpp/include/rclcpp/logger.hpp b/rclcpp/include/rclcpp/logger.hpp new file mode 100644 index 0000000..e9b110b --- /dev/null +++ b/rclcpp/include/rclcpp/logger.hpp @@ -0,0 +1,131 @@ +// Copyright 2017 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__LOGGER_HPP_ +#define RCLCPP__LOGGER_HPP_ + +#include +#include + +#include "rclcpp/visibility_control.hpp" + +/** + * \def RCLCPP_LOGGING_ENABLED + * When this define evaluates to true (default), logger factory functions will + * behave normally. + * When false, logger factory functions will create dummy loggers to avoid + * computational expense in manipulating objects. + * This should be used in combination with `RCLCPP_LOG_MIN_SEVERITY` to compile + * out logging macros. + */ +// TODO(dhood): determine this automatically from `RCLCPP_LOG_MIN_SEVERITY` +#ifndef RCLCPP_LOGGING_ENABLED +#define RCLCPP_LOGGING_ENABLED 1 +#endif + +namespace rclcpp +{ + +// Forward declaration is used for friend statement. +namespace node_interfaces +{ +class NodeLogging; +} + +class Logger; + +/// Return a named logger. +/** + * The returned logger's name will include any naming conventions, such as a + * name prefix. + * Currently there are no such naming conventions but they may be introduced in + * the future. + * + * \param[in] name the name of the logger + * \return a logger with the fully-qualified name including naming conventions, or + * \return a dummy logger if logging is disabled. + */ +RCLCPP_PUBLIC +Logger +get_logger(const std::string & name); + +class Logger +{ +private: + friend Logger rclcpp::get_logger(const std::string & name); + friend ::rclcpp::node_interfaces::NodeLogging; + + /// Constructor of a dummy logger. + /** + * This is used when logging is disabled: see `RCLCPP_LOGGING_ENABLED`. + * This cannot be called directly, see `rclcpp::get_logger` instead. + */ + Logger() + : name_(nullptr) {} + + /// Constructor of a named logger. + /** + * This cannot be called directly, see `rclcpp::get_logger` instead. + */ + explicit Logger(const std::string & name) + : name_(new std::string(name)) {} + + std::shared_ptr name_; + +public: + RCLCPP_PUBLIC + Logger(const Logger &) = default; + + /// Get the name of this logger. + /** + * \return the full name of the logger including any prefixes, or + * \return `nullptr` if this logger is invalid (e.g. because logging is + * disabled). + */ + RCLCPP_PUBLIC + const char * + get_name() const + { + if (!name_) { + return nullptr; + } + return name_->c_str(); + } + + /// Return a logger that is a descendant of this logger. + /** + * The child logger's full name will include any hierarchy conventions that + * indicate it is a descendant of this logger. + * For example, ```get_logger('abc').get_child('def')``` will return a logger + * with name `abc.def`. + * + * \param[in] suffix the child logger's suffix + * \return a logger with the fully-qualified name including the suffix, or + * \return a dummy logger if this logger is invalid (e.g. because logging is + * disabled). + */ + RCLCPP_PUBLIC + Logger + get_child(const std::string & suffix) + { + if (!name_) { + return Logger(); + } + return Logger(*name_ + "." + suffix); + } +}; + +} // namespace rclcpp + +#endif // RCLCPP__LOGGER_HPP_ diff --git a/rclcpp/include/rclcpp/node.hpp b/rclcpp/include/rclcpp/node.hpp index bec9954..942e750 100644 --- a/rclcpp/include/rclcpp/node.hpp +++ b/rclcpp/include/rclcpp/node.hpp @@ -37,11 +37,13 @@ #include "rclcpp/client.hpp" #include "rclcpp/context.hpp" #include "rclcpp/event.hpp" +#include "rclcpp/logger.hpp" #include "rclcpp/macros.hpp" #include "rclcpp/message_memory_strategy.hpp" #include "rclcpp/node_interfaces/node_base_interface.hpp" #include "rclcpp/node_interfaces/node_clock_interface.hpp" #include "rclcpp/node_interfaces/node_graph_interface.hpp" +#include "rclcpp/node_interfaces/node_logging_interface.hpp" #include "rclcpp/node_interfaces/node_parameters_interface.hpp" #include "rclcpp/node_interfaces/node_services_interface.hpp" #include "rclcpp/node_interfaces/node_timers_interface.hpp" @@ -108,6 +110,12 @@ public: const char * get_namespace() const; + /// Get the logger of the node. + /** \return The logger of the node. */ + RCLCPP_PUBLIC + rclcpp::Logger + get_logger() const; + /// Create and return a callback group. RCLCPP_PUBLIC rclcpp::callback_group::CallbackGroup::SharedPtr @@ -412,6 +420,7 @@ private: rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_; rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_; + rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_; rclcpp::node_interfaces::NodeTimersInterface::SharedPtr node_timers_; rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_; rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_; diff --git a/rclcpp/include/rclcpp/node_interfaces/node_logging.hpp b/rclcpp/include/rclcpp/node_interfaces/node_logging.hpp new file mode 100644 index 0000000..0cffed1 --- /dev/null +++ b/rclcpp/include/rclcpp/node_interfaces/node_logging.hpp @@ -0,0 +1,61 @@ +// Copyright 2017 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__NODE_INTERFACES__NODE_LOGGING_HPP_ +#define RCLCPP__NODE_INTERFACES__NODE_LOGGING_HPP_ + +#include + +#include "rclcpp/logger.hpp" +#include "rclcpp/macros.hpp" +#include "rclcpp/node_interfaces/node_base_interface.hpp" +#include "rclcpp/node_interfaces/node_logging_interface.hpp" +#include "rclcpp/visibility_control.hpp" + +namespace rclcpp +{ +namespace node_interfaces +{ + +/// Implementation of the NodeLogging part of the Node API. +class NodeLogging : public NodeLoggingInterface +{ +public: + RCLCPP_SMART_PTR_ALIASES_ONLY(NodeLoggingInterface) + + RCLCPP_PUBLIC + explicit NodeLogging(rclcpp::node_interfaces::NodeBaseInterface * node_base); + + RCLCPP_PUBLIC + virtual + ~NodeLogging(); + + RCLCPP_PUBLIC + virtual + rclcpp::Logger + get_logger() const; + +private: + RCLCPP_DISABLE_COPY(NodeLogging) + + /// Handle to the NodeBaseInterface given in the constructor. + rclcpp::node_interfaces::NodeBaseInterface * node_base_; + + rclcpp::Logger logger_; +}; + +} // namespace node_interfaces +} // namespace rclcpp + +#endif // RCLCPP__NODE_INTERFACES__NODE_LOGGING_HPP_ diff --git a/rclcpp/include/rclcpp/node_interfaces/node_logging_interface.hpp b/rclcpp/include/rclcpp/node_interfaces/node_logging_interface.hpp new file mode 100644 index 0000000..c549ca2 --- /dev/null +++ b/rclcpp/include/rclcpp/node_interfaces/node_logging_interface.hpp @@ -0,0 +1,47 @@ +// Copyright 2017 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__NODE_INTERFACES__NODE_LOGGING_INTERFACE_HPP_ +#define RCLCPP__NODE_INTERFACES__NODE_LOGGING_INTERFACE_HPP_ + +#include + +#include "rclcpp/logger.hpp" +#include "rclcpp/macros.hpp" +#include "rclcpp/node_interfaces/node_base_interface.hpp" +#include "rclcpp/visibility_control.hpp" + +namespace rclcpp +{ +namespace node_interfaces +{ + +/// Pure virtual interface class for the NodeLogging part of the Node API. +class NodeLoggingInterface +{ +public: + RCLCPP_SMART_PTR_ALIASES_ONLY(NodeLoggingInterface) + + /// Return the logger of the node. + /** \return The logger of the node. */ + RCLCPP_PUBLIC + virtual + rclcpp::Logger + get_logger() const = 0; +}; + +} // namespace node_interfaces +} // namespace rclcpp + +#endif // RCLCPP__NODE_INTERFACES__NODE_LOGGING_INTERFACE_HPP_ diff --git a/rclcpp/include/rclcpp/rclcpp.hpp b/rclcpp/include/rclcpp/rclcpp.hpp index 54881b2..3156d71 100644 --- a/rclcpp/include/rclcpp/rclcpp.hpp +++ b/rclcpp/include/rclcpp/rclcpp.hpp @@ -17,7 +17,7 @@ * `rclcpp` provides the canonical C++ API for interacting with ROS. * It consists of these main components: * - * - Nodes + * - Node * - rclcpp::node::Node * - rclcpp/node.hpp * - Publisher @@ -93,6 +93,20 @@ * - rclcpp::node::Node::count_publishers() * - rclcpp::node::Node::count_subscribers() * + * And components related to logging: + * + * - Logging macros: + * - Some examples (not exhaustive): + * - RCLCPP_DEBUG() + * - RCLCPP_INFO() + * - RCLCPP_WARN_ONCE() + * - RCLCPP_ERROR_SKIPFIRST() + * - rclcpp/logging.hpp + * - Logger: + * - rclcpp::Logger + * - rclcpp/logger.hpp + * - rclcpp::node::Node::get_logger() + * * Finally, there are many internal API's and utilities: * * - Exceptions: @@ -110,13 +124,6 @@ * - rclcpp::context::Context * - rclcpp/context.hpp * - rclcpp/contexts/default_context.hpp - * - Logging macros: - * - Some examples (not exhaustive): - * - RCLCPP_DEBUG() - * - RCLCPP_INFO() - * - RCLCPP_WARN_ONCE() - * - RCLCPP_ERROR_SKIPFIRST() - * - rclcpp/logging.hpp * - Various utilities: * - rclcpp/function_traits.hpp * - rclcpp/macros.hpp diff --git a/rclcpp/resource/logging.hpp.em b/rclcpp/resource/logging.hpp.em index badef9b..238f019 100644 --- a/rclcpp/resource/logging.hpp.em +++ b/rclcpp/resource/logging.hpp.em @@ -17,6 +17,9 @@ #ifndef RCLCPP__LOGGING_HPP_ #define RCLCPP__LOGGING_HPP_ +#include + +#include "rclcpp/logger.hpp" #include "rcutils/logging_macros.h" // These are used for compiling out logging macros lower than a minimum severity. @@ -31,13 +34,12 @@ * \def RCLCPP_LOG_MIN_SEVERITY * Define RCLCPP_LOG_MIN_SEVERITY=RCLCPP_LOG_MIN_SEVERITY_[DEBUG|INFO|WARN|ERROR|FATAL] * in your build options to compile out anything below that severity. - * Use RCUTILS_LOG_MIN_SEVERITY_NONE to compile out all macros. + * Use RCLCPP_LOG_MIN_SEVERITY_NONE to compile out all macros. */ #ifndef RCLCPP_LOG_MIN_SEVERITY #define RCLCPP_LOG_MIN_SEVERITY RCLCPP_LOG_MIN_SEVERITY_DEBUG #endif - @{ from rcutils.logging import feature_combinations from rcutils.logging import get_macro_parameters @@ -76,20 +78,20 @@ def is_supported_feature_combination(feature_combination): @[ for doc_line in feature_combinations[feature_combination].doc_lines]@ * @(doc_line) @[ end for]@ - * \param name The name of the logger + * \param logger The `rclcpp::Logger` to use @[ for param_name, doc_line in feature_combinations[feature_combination].params.items()]@ * \param @(param_name) @(doc_line) @[ end for]@ * \param ... The format string, followed by the variable arguments for the format string */ -// TODO(dhood): Replace the name argument with a logger object. -#define RCLCPP_@(severity)@(suffix)(name, @(''.join([p + ', ' for p in get_macro_parameters(feature_combination).keys()]))...) \ +#define RCLCPP_@(severity)@(suffix)(logger, @(''.join([p + ', ' for p in get_macro_parameters(feature_combination).keys()]))...) \ + static_assert(::std::is_same::value, "First argument to logging macros must be an rclcpp::Logger"); \ RCUTILS_LOG_@(severity)@(suffix)_NAMED( \ @{params = get_macro_parameters(feature_combination).keys()}@ @[ if params]@ @(''.join([' ' + p + ', \\\n' for p in params]))@ @[ end if]@ - std::string(name).c_str(), \ + logger.get_name(), \ __VA_ARGS__) @[ end for]@ diff --git a/rclcpp/src/rclcpp/logger.cpp b/rclcpp/src/rclcpp/logger.cpp new file mode 100644 index 0000000..03b5e0c --- /dev/null +++ b/rclcpp/src/rclcpp/logger.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "rclcpp/logger.hpp" + +namespace rclcpp +{ + +rclcpp::Logger +get_logger(const std::string & name) +{ +#if RCLCPP_LOGGING_ENABLED + return rclcpp::Logger(name); +#else + (void)name; + return rclcpp::Logger(); +#endif +} + +} // namespace rclcpp diff --git a/rclcpp/src/rclcpp/node.cpp b/rclcpp/src/rclcpp/node.cpp index 82c807e..3e29a94 100644 --- a/rclcpp/src/rclcpp/node.cpp +++ b/rclcpp/src/rclcpp/node.cpp @@ -26,6 +26,7 @@ #include "rclcpp/node_interfaces/node_base.hpp" #include "rclcpp/node_interfaces/node_clock.hpp" #include "rclcpp/node_interfaces/node_graph.hpp" +#include "rclcpp/node_interfaces/node_logging.hpp" #include "rclcpp/node_interfaces/node_parameters.hpp" #include "rclcpp/node_interfaces/node_services.hpp" #include "rclcpp/node_interfaces/node_timers.hpp" @@ -52,6 +53,7 @@ Node::Node( bool use_intra_process_comms) : node_base_(new rclcpp::node_interfaces::NodeBase(node_name, namespace_, context)), node_graph_(new rclcpp::node_interfaces::NodeGraph(node_base_.get())), + node_logging_(new rclcpp::node_interfaces::NodeLogging(node_base_.get())), node_timers_(new rclcpp::node_interfaces::NodeTimers(node_base_.get())), node_topics_(new rclcpp::node_interfaces::NodeTopics(node_base_.get())), node_services_(new rclcpp::node_interfaces::NodeServices(node_base_.get())), @@ -84,6 +86,12 @@ Node::get_namespace() const return node_base_->get_namespace(); } +rclcpp::Logger +Node::get_logger() const +{ + return node_logging_->get_logger(); +} + rclcpp::callback_group::CallbackGroup::SharedPtr Node::create_callback_group( rclcpp::callback_group::CallbackGroupType group_type) diff --git a/rclcpp/src/rclcpp/node_interfaces/node_logging.cpp b/rclcpp/src/rclcpp/node_interfaces/node_logging.cpp new file mode 100644 index 0000000..bba4d49 --- /dev/null +++ b/rclcpp/src/rclcpp/node_interfaces/node_logging.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rclcpp/node_interfaces/node_logging.hpp" + +using rclcpp::node_interfaces::NodeLogging; + +NodeLogging::NodeLogging(rclcpp::node_interfaces::NodeBaseInterface * node_base) +: node_base_(node_base) +{ + // TODO(dhood): use the namespace (slashes converted to dots) + logger_ = rclcpp::get_logger(node_base_->get_name()); +} + +NodeLogging::~NodeLogging() +{ +} + +rclcpp::Logger +NodeLogging::get_logger() const +{ + return logger_; +} diff --git a/rclcpp/test/test_logger.cpp b/rclcpp/test/test_logger.cpp new file mode 100644 index 0000000..258cdd0 --- /dev/null +++ b/rclcpp/test/test_logger.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include + +#include "rclcpp/logger.hpp" +#include "rclcpp/logging.hpp" + +TEST(TestLogger, factory_functions) { + rclcpp::Logger logger = rclcpp::get_logger("test_logger"); + EXPECT_STREQ("test_logger", logger.get_name()); + rclcpp::Logger logger_copy = rclcpp::Logger(logger); + EXPECT_STREQ("test_logger", logger_copy.get_name()); +} + +TEST(TestLogger, hierarchy) { + rclcpp::Logger logger = rclcpp::get_logger("test_logger"); + rclcpp::Logger sublogger = logger.get_child("child"); + EXPECT_STREQ("test_logger.child", sublogger.get_name()); + rclcpp::Logger subsublogger = sublogger.get_child("grandchild"); + EXPECT_STREQ("test_logger.child.grandchild", subsublogger.get_name()); +} diff --git a/rclcpp/test/test_logging.cpp b/rclcpp/test/test_logging.cpp index b316c32..323a3ab 100644 --- a/rclcpp/test/test_logging.cpp +++ b/rclcpp/test/test_logging.cpp @@ -19,15 +19,15 @@ #include #include +#include "rclcpp/logger.hpp" #include "rclcpp/logging.hpp" #include "rcutils/logging.h" #include "rcutils/time.h" -#define RCLCPP_TEST_LOGGING_MACRO_NAME "name" // Used in testing below - using ::testing::EndsWith; size_t g_log_calls = 0; +rclcpp::Logger g_logger = rclcpp::get_logger("name"); struct LogEvent { @@ -75,7 +75,7 @@ public: TEST_F(TestLoggingMacros, test_logging_named) { for (int i : {1, 2, 3}) { - RCLCPP_DEBUG("name", "message %d", i); + RCLCPP_DEBUG(g_logger, "message %d", i); } EXPECT_EQ(3u, g_log_calls); EXPECT_TRUE(g_last_log_event.location != NULL); @@ -87,28 +87,11 @@ TEST_F(TestLoggingMacros, test_logging_named) { EXPECT_EQ(RCUTILS_LOG_SEVERITY_DEBUG, g_last_log_event.level); EXPECT_EQ("name", g_last_log_event.name); EXPECT_EQ("message 3", g_last_log_event.message); - - // Test different name inputs - std::string std_string_name = "name"; - RCLCPP_DEBUG(std_string_name, "message"); - EXPECT_EQ("name", g_last_log_event.name); - - const char * c_string_name = "name"; - RCLCPP_DEBUG(c_string_name, "message"); - EXPECT_EQ("name", g_last_log_event.name); - - RCLCPP_DEBUG(std_string_name + c_string_name, "message"); - EXPECT_EQ("namename", g_last_log_event.name); - - RCLCPP_DEBUG(RCLCPP_TEST_LOGGING_MACRO_NAME, "message"); - EXPECT_EQ(RCLCPP_TEST_LOGGING_MACRO_NAME, g_last_log_event.name); - RCLCPP_DEBUG(std::string(RCLCPP_TEST_LOGGING_MACRO_NAME) + std_string_name, "message"); - EXPECT_EQ("namename", g_last_log_event.name); } TEST_F(TestLoggingMacros, test_logging_once) { for (int i : {1, 2, 3}) { - RCLCPP_INFO_ONCE("name", "message %d", i); + RCLCPP_INFO_ONCE(g_logger, "message %d", i); } EXPECT_EQ(1u, g_log_calls); EXPECT_EQ(RCUTILS_LOG_SEVERITY_INFO, g_last_log_event.level); @@ -118,7 +101,7 @@ TEST_F(TestLoggingMacros, test_logging_once) { // Check that another instance has a context that's independent to the call above's g_log_calls = 0; for (int i : {1, 2, 3}) { - RCLCPP_INFO_ONCE("name", "second message %d", i); + RCLCPP_INFO_ONCE(g_logger, "second message %d", i); } EXPECT_EQ(1u, g_log_calls); EXPECT_EQ(RCUTILS_LOG_SEVERITY_INFO, g_last_log_event.level); @@ -128,7 +111,7 @@ TEST_F(TestLoggingMacros, test_logging_once) { TEST_F(TestLoggingMacros, test_logging_expression) { for (int i : {1, 2, 3, 4, 5, 6}) { - RCLCPP_INFO_EXPRESSION("name", i % 3, "message %d", i); + RCLCPP_INFO_EXPRESSION(g_logger, i % 3, "message %d", i); } EXPECT_EQ(4u, g_log_calls); EXPECT_EQ("message 5", g_last_log_event.message); @@ -144,7 +127,7 @@ bool mod3() TEST_F(TestLoggingMacros, test_logging_function) { for (int i : {1, 2, 3, 4, 5, 6}) { g_counter = i; - RCLCPP_INFO_FUNCTION("name", &mod3, "message %d", i); + RCLCPP_INFO_FUNCTION(g_logger, &mod3, "message %d", i); } EXPECT_EQ(4u, g_log_calls); EXPECT_EQ("message 5", g_last_log_event.message); @@ -152,7 +135,7 @@ TEST_F(TestLoggingMacros, test_logging_function) { TEST_F(TestLoggingMacros, test_logging_skipfirst) { for (uint32_t i : {1, 2, 3, 4, 5}) { - RCLCPP_WARN_SKIPFIRST("name", "message %u", i); + RCLCPP_WARN_SKIPFIRST(g_logger, "message %u", i); EXPECT_EQ(i - 1, g_log_calls); } } diff --git a/rclcpp/test/test_node.cpp b/rclcpp/test/test_node.cpp index 7230aa5..b1781a5 100644 --- a/rclcpp/test/test_node.cpp +++ b/rclcpp/test/test_node.cpp @@ -74,6 +74,18 @@ TEST_F(TestNode, get_name_and_namespace) { } } +TEST_F(TestNode, get_logger) { + // Currently the namespace is not taken into account with the node logger name + { + auto node = std::make_shared("my_node"); + EXPECT_STREQ("my_node", node->get_logger().get_name()); + } + { + auto node = std::make_shared("my_node", "/ns"); + EXPECT_STREQ("my_node", node->get_logger().get_name()); + } +} + TEST_F(TestNode, get_clock) { auto node = std::make_shared("my_node", "/ns"); auto ros_clock = node->get_clock(); diff --git a/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp b/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp index 8b2d1b7..5453502 100644 --- a/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp +++ b/rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp @@ -32,10 +32,12 @@ #include "rclcpp/client.hpp" #include "rclcpp/context.hpp" #include "rclcpp/event.hpp" +#include "rclcpp/logger.hpp" #include "rclcpp/macros.hpp" #include "rclcpp/message_memory_strategy.hpp" #include "rclcpp/node_interfaces/node_base_interface.hpp" #include "rclcpp/node_interfaces/node_graph_interface.hpp" +#include "rclcpp/node_interfaces/node_logging_interface.hpp" #include "rclcpp/node_interfaces/node_parameters_interface.hpp" #include "rclcpp/node_interfaces/node_services_interface.hpp" #include "rclcpp/node_interfaces/node_timers_interface.hpp" @@ -108,6 +110,12 @@ public: const char * get_namespace() const; + /// Get the logger of the node. + /** \return The logger of the node. */ + RCLCPP_LIFECYCLE_PUBLIC + rclcpp::Logger + get_logger() const; + /// Create and return a callback group. RCLCPP_LIFECYCLE_PUBLIC rclcpp::callback_group::CallbackGroup::SharedPtr @@ -467,6 +475,7 @@ private: rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_; rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_; + rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_; rclcpp::node_interfaces::NodeTimersInterface::SharedPtr node_timers_; rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_; rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_; diff --git a/rclcpp_lifecycle/src/lifecycle_node.cpp b/rclcpp_lifecycle/src/lifecycle_node.cpp index ad5bd26..4d9ec2f 100644 --- a/rclcpp_lifecycle/src/lifecycle_node.cpp +++ b/rclcpp_lifecycle/src/lifecycle_node.cpp @@ -25,9 +25,11 @@ #include "rclcpp/exceptions.hpp" #include "rclcpp/graph_listener.hpp" +#include "rclcpp/logger.hpp" #include "rclcpp/node.hpp" #include "rclcpp/node_interfaces/node_base.hpp" #include "rclcpp/node_interfaces/node_graph.hpp" +#include "rclcpp/node_interfaces/node_logging.hpp" #include "rclcpp/node_interfaces/node_parameters.hpp" #include "rclcpp/node_interfaces/node_services.hpp" #include "rclcpp/node_interfaces/node_timers.hpp" @@ -56,6 +58,7 @@ LifecycleNode::LifecycleNode( bool use_intra_process_comms) : node_base_(new rclcpp::node_interfaces::NodeBase(node_name, namespace_, context)), node_graph_(new rclcpp::node_interfaces::NodeGraph(node_base_.get())), + node_logging_(new rclcpp::node_interfaces::NodeLogging(node_base_.get())), node_timers_(new rclcpp::node_interfaces::NodeTimers(node_base_.get())), node_topics_(new rclcpp::node_interfaces::NodeTopics(node_base_.get())), node_services_(new rclcpp::node_interfaces::NodeServices(node_base_.get())), @@ -95,6 +98,12 @@ LifecycleNode::get_namespace() const return node_base_->get_namespace(); } +rclcpp::Logger +LifecycleNode::get_logger() const +{ + return node_logging_->get_logger(); +} + rclcpp::callback_group::CallbackGroup::SharedPtr LifecycleNode::create_callback_group( rclcpp::callback_group::CallbackGroupType group_type)