API for review
It's a very simple API, so I'm mainly just going to throw up the actual header I've come up with.
The basic exposed features:
- There's very little inside the ros::console namespace. What's in there is mostly for use by the macros, or if you want to do something special (like add your own appender). The common API is all macro-based.
- The ROS_X macros provide printf-style output
- The ROS_X_STREAM macros provide C++ stream-style output
- ROSCONSOLE_MIN_SEVERITY provides a way to compile-out messages below a specified severity (should be unnecessary in most cases)
Here's the header:
#include "log4cxx/logger.h" #include "rosthread/mutex.h" /** * \file */ namespace ros { namespace console { /** * \brief Only exported because the macros need it. Do not use directly. */ extern bool g_initialized; /** * \brief Only exported because the macros need it. Do not use directly. */ extern log4cxx::LoggerPtr g_logger; /** * \brief Don't call this directly. Performs any required initialization/configuration. Happens automatically when using the macro API. * * If you're going to be using log4cxx or any of the ros::console functions, and need the system to be initialized, use the * ROSCONSOLE_AUTOINIT macro. */ void initialize(); /** * \brief Don't call this directly. Use the ROS_LOG() macro instead. * @param level Logging level * @param file File this logging statement is from (usually generated with __FILE__) * @param line Line of code this logging statement is from (usually generated with __LINE__) * @param fmt Format string */ void print(const log4cxx::LevelPtr& level, const char* file, const int line, const char* fmt, ...); /** * \brief Get the logger rosconsole uses for its output * @return The log4cxx logger */ inline const log4cxx::LoggerPtr& getLogger() { return g_logger; } } // namespace console } // namespace ros // These allow you to compile-out everything below a certain severity level if necessary #define ROSCONSOLE_SEVERITY_DEBUG 0 #define ROSCONSOLE_SEVERITY_INFO 1 #define ROSCONSOLE_SEVERITY_WARN 2 #define ROSCONSOLE_SEVERITY_ERROR 3 #define ROSCONSOLE_SEVERITY_FATAL 4 // Define ROSCONSOLE_MIN_SEVERITY=ROSCONSOLE_SEVERITY_[DEBUG|INFO|WARN|ERROR|FATAL] to compile out anything below that severity #ifndef ROSCONSOLE_MIN_SEVERITY #define ROSCONSOLE_MIN_SEVERITY ROSCONSOLE_SEVERITY_DEBUG #endif /** * \def ROSCONSOLE_AUTOINIT * \brief Initializes the rosconsole library. Usually unnecessary to call directly. */ #define ROSCONSOLE_AUTOINIT \ do \ { \ if (!ros::console::g_initialized) \ { \ initialize(); \ } \ } while(0) /** * \brief Prints a log statement at the specified severity level * \param level A log4cxx::LevelPtr specifying the severity level * * Uses printf format-string style, eg: @verbatim ROS_LOG(log4cxx::Level::ERROR, "%d: %s\n", my_int, my_string.c_str()); @endverbatim */ #define ROS_LOG(level, ...) \ do \ { \ ROSCONSOLE_AUTOINIT; \ if ( ros::console::g_logger->isEnabledFor(level) ) \ { \ ros::console::print( level, __FILE__, __LINE__, __VA_ARGS__); \ } \ } while(0) #if (ROSCONSOLE_MIN_SEVERITY > ROSCONSOLE_SEVERITY_INFO) #define ROS_INFO(...) #else /** * \brief Prints a log statement at the INFO severity level. * * Uses printf format-string style, eg: @verbatim ROS_INFO("%d: %s\n", my_int, my_string.c_str()); @endverbatim */ #define ROS_INFO(...) \ do \ { \ ROSCONSOLE_AUTOINIT; \ if ( ros::console::g_logger->isInfoEnabled() ) \ { \ ros::console::print( log4cxx::Level::INFO, __FILE__, __LINE__, __VA_ARGS__); \ } \ } while(0) #endif #if (ROSCONSOLE_MIN_SEVERITY > ROSCONSOLE_SEVERITY_DEBUG) #define ROS_DEBUG(...) #else /** * \brief Prints a log statement at the DEBUG severity level * * Uses printf format-string style, eg: @verbatim ROS_DEBUG("%d: %s\n", my_int, my_string.c_str()); @endverbatim */ #define ROS_DEBUG(...) \ do \ { \ ROSCONSOLE_AUTOINIT; \ if ( ros::console::g_logger->isDebugEnabled() ) \ { \ ros::console::print( log4cxx::Level::DEBUG, __FILE__, __LINE__, __VA_ARGS__); \ } \ } while(0) #endif #if (ROSCONSOLE_MIN_SEVERITY > ROSCONSOLE_SEVERITY_WARN) #define ROS_WARN(...) #else /** * \brief Prints a log statement at the WARN severity level * * Uses printf format-string style, eg: @verbatim ROS_WARN("%d: %s\n", my_int, my_string.c_str()); @endverbatim */ #define ROS_WARN(...) \ do \ { \ ROSCONSOLE_AUTOINIT; \ if ( ros::console::g_logger->isWarnEnabled() ) \ { \ ros::console::print( log4cxx::Level::WARN, __FILE__, __LINE__, __VA_ARGS__); \ } \ } while(0) #endif #if (ROSCONSOLE_MIN_SEVERITY > ROSCONSOLE_SEVERITY_ERROR) #define ROS_ERROR(...) #else /** * \brief Prints a log statement at the ERROR severity level * * Uses printf format-string style, eg: @verbatim ROS_ERROR("%d: %s\n", my_int, my_string.c_str()); @endverbatim */ #define ROS_ERROR(...) \ do \ { \ ROSCONSOLE_AUTOINIT; \ if ( ros::console::g_logger->isErrorEnabled() ) \ { \ ros::console::print( log4cxx::Level::ERROR, __FILE__, __LINE__, __VA_ARGS__); \ } \ } while(0) #endif #if (ROSCONSOLE_MIN_SEVERITY > ROSCONSOLE_SEVERITY_FATAL) #define ROS_FATAL(...) #else /** * \brief Prints a log statement at the FATAL severity level * * Uses printf format-string style, eg: @verbatim ROS_FATAL("%d: %s\n", my_int, my_string.c_str()); @endverbatim */ #define ROS_FATAL(...) \ do \ { \ ROSCONSOLE_AUTOINIT; \ if ( ros::console::g_logger->isFatalEnabled() ) \ { \ ros::console::print( log4cxx::Level::FATAL, __FILE__, __LINE__, __VA_ARGS__); \ } \ } while(0) #endif /** * \brief Prints out a log statement at the specified severity level * * Uses C++ stream-style, eg: @verbatim ROS_LOG_STREAM(log4cxx::Level::ERROR, my_int << ": " << my_string); @endverbatim */ #define ROS_LOG_STREAM(level, args) \ do \ { \ ROSCONSOLE_AUTOINIT; \ LOG4CXX_LOG( ros::console::g_logger, level, args ); \ } while(0) #if (ROSCONSOLE_MIN_SEVERITY > ROSCONSOLE_SEVERITY_INFO) #define ROS_INFO_STREAM(args) #else /** * \brief Prints out a log statement at the INFO severity level * * Uses C++ stream-style, eg: @verbatim ROS_INFO_STREAM(my_int << ": " << my_string); @endverbatim */ #define ROS_INFO_STREAM(args) \ do \ { \ ROSCONSOLE_AUTOINIT; \ LOG4CXX_INFO( ros::console::g_logger, args ); \ } while(0) #endif #if (ROSCONSOLE_MIN_SEVERITY > ROSCONSOLE_SEVERITY_DEBUG) #define ROS_DEBUG_STREAM(args) #else /** * \brief Prints out a log statement at the DEBUG severity level * * Uses C++ stream-style, eg: @verbatim ROS_DEBUG_STREAM(my_int << ": " << my_string); @endverbatim */ #define ROS_DEBUG_STREAM(args) \ do \ { \ ROSCONSOLE_AUTOINIT; \ LOG4CXX_DEBUG( ros::console::g_logger, args ); \ } while(0) #endif #if (ROSCONSOLE_MIN_SEVERITY > ROSCONSOLE_SEVERITY_WARN) #define ROS_WARN_STREAM(args) #else /** * \brief Prints out a log statement at the WARN severity level * * Uses C++ stream-style, eg: @verbatim ROS_WARN_STREAM(my_int << ": " << my_string); @endverbatim */ #define ROS_WARN_STREAM(args) \ do \ { \ ROSCONSOLE_AUTOINIT; \ LOG4CXX_WARN( ros::console::g_logger, args ); \ } while(0) #endif #if (ROSCONSOLE_MIN_SEVERITY > ROSCONSOLE_SEVERITY_ERROR) #define ROS_ERROR_STREAM(args) #else /** * \brief Prints out a log statement at the ERROR severity level * * Uses C++ stream-style, eg: @verbatim ROS_ERROR_STREAM(my_int << ": " << my_string); @endverbatim */ #define ROS_ERROR_STREAM(args) \ do \ { \ ROSCONSOLE_AUTOINIT; \ LOG4CXX_ERROR( ros::console::g_logger, args ); \ } while(0) #endif #if (ROSCONSOLE_MIN_SEVERITY > ROSCONSOLE_SEVERITY_FATAL) #define ROS_FATAL_STREAM(args) #else /** * \brief Prints out a log statement at the FATAL severity level * * Uses C++ stream-style, eg: @verbatim ROS_FATAL_STREAM(my_int << ": " << my_string); @endverbatim */ #define ROS_FATAL_STREAM(args) \ do \ { \ ROSCONSOLE_AUTOINIT; \ LOG4CXX_FATAL( ros::console::g_logger, args ); \ } while(0) #endif