00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef ROSCONSOLE_ROSCONSOLE_H
00033 #define ROSCONSOLE_ROSCONSOLE_H
00034
00035 #include <cstdio>
00036 #include <sstream>
00037 #include <ros/time.h>
00038 #include <cstdarg>
00039 #include <ros/macros.h>
00040
00041
00042
00043 #ifdef ROS_BUILD_SHARED_LIBS // ros is being built around shared libraries
00044 #ifdef rosconsole_EXPORTS // we are building a shared lib/dll
00045 #define ROSCONSOLE_DECL ROS_HELPER_EXPORT
00046 #else // we are using shared lib/dll
00047 #define ROSCONSOLE_DECL ROS_HELPER_IMPORT
00048 #endif
00049 #else // ros is being built around static libraries
00050 #define ROSCONSOLE_DECL
00051 #endif
00052
00053
00054
00055 #include <log4cxx/logger.h>
00056
00057 #ifdef __GNUC__
00058 #if __GNUC__ >= 3
00059 #define ROSCONSOLE_PRINTF_ATTRIBUTE(a, b) __attribute__ ((__format__ (__printf__, a, b)));
00060 #endif
00061 #endif
00062
00063 #ifndef ROSCONSOLE_PRINTF_ATTRIBUTE
00064 #define ROSCONSOLE_PRINTF_ATTRIBUTE(a, b)
00065 #endif
00066
00067
00068 namespace log4cxx
00069 {
00070 namespace helpers
00071 {
00072 template<typename T> class ObjectPtrT;
00073 }
00074
00075 class Level;
00076 typedef helpers::ObjectPtrT<Level> LevelPtr;
00077
00078 class Logger;
00079 typedef helpers::ObjectPtrT<Logger> LoggerPtr;
00080 }
00081
00082 namespace boost
00083 {
00084 template<typename T> class shared_array;
00085 }
00086
00087 namespace ros
00088 {
00089 namespace console
00090 {
00091
00092 ROSCONSOLE_DECL void shutdown();
00093
00094 namespace levels
00095 {
00096 enum Level
00097 {
00098 Debug,
00099 Info,
00100 Warn,
00101 Error,
00102 Fatal,
00103
00104 Count
00105 };
00106 }
00107 typedef levels::Level Level;
00108
00109 extern ROSCONSOLE_DECL log4cxx::LevelPtr g_level_lookup[];
00110
00114 extern ROSCONSOLE_DECL bool g_initialized;
00115
00122 ROSCONSOLE_DECL void initialize();
00123
00124 class FilterBase;
00132 ROSCONSOLE_DECL void print(FilterBase* filter, log4cxx::Logger* logger, Level level,
00133 const char* file, int line,
00134 const char* function, const char* fmt, ...) ROSCONSOLE_PRINTF_ATTRIBUTE(7, 8);
00135
00136 ROSCONSOLE_DECL void print(FilterBase* filter, log4cxx::Logger* logger, Level level,
00137 const std::stringstream& str, const char* file, int line, const char* function);
00138
00139 struct ROSCONSOLE_DECL LogLocation;
00140
00148 ROSCONSOLE_DECL void registerLogLocation(LogLocation* loc);
00149
00158 ROSCONSOLE_DECL void notifyLoggerLevelsChanged();
00159
00160 ROSCONSOLE_DECL void setFixedFilterToken(const std::string& key, const std::string& val);
00161
00165 struct FilterParams
00166 {
00167
00168 const char* file;
00169 int line;
00170 const char* function;
00171 const char* message;
00172
00173
00174 log4cxx::LoggerPtr logger;
00175 Level level;
00176
00177
00178 std::string out_message;
00179 };
00180
00202 class FilterBase
00203 {
00204 public:
00205 virtual ~FilterBase() {}
00210 inline virtual bool isEnabled() { return true; }
00215 inline virtual bool isEnabled(FilterParams&) { return true; }
00216 };
00217
00218 struct ROSCONSOLE_DECL LogLocation;
00222 ROSCONSOLE_DECL void initializeLogLocation(LogLocation* loc, const std::string& name, Level level);
00226 ROSCONSOLE_DECL void setLogLocationLevel(LogLocation* loc, Level level);
00230 ROSCONSOLE_DECL void checkLogLocationEnabled(LogLocation* loc);
00231
00235 struct LogLocation
00236 {
00237 bool initialized_;
00238 bool logger_enabled_;
00239 ::ros::console::Level level_;
00240 log4cxx::Logger* logger_;
00241 };
00242
00243 ROSCONSOLE_DECL void vformatToBuffer(boost::shared_array<char>& buffer, size_t& buffer_size, const char* fmt, va_list args);
00244 ROSCONSOLE_DECL void formatToBuffer(boost::shared_array<char>& buffer, size_t& buffer_size, const char* fmt, ...);
00245 ROSCONSOLE_DECL std::string formatToString(const char* fmt, ...);
00246
00247 }
00248 }
00249
00250 #ifdef WIN32
00251 #define ROS_LIKELY(x) (x)
00252 #define ROS_UNLIKELY(x) (x)
00253 #else
00254 #define ROS_LIKELY(x) __builtin_expect((x),1)
00255 #define ROS_UNLIKELY(x) __builtin_expect((x),0)
00256 #endif
00257
00258 #if defined(MSVC)
00259 #define __ROSCONSOLE_FUNCTION__ __FUNCSIG__
00260 #elif defined(__GNUC__)
00261 #define __ROSCONSOLE_FUNCTION__ __PRETTY_FUNCTION__
00262 #else
00263 #define __ROSCONSOLE_FUNCTION__ ""
00264 #endif
00265
00266
00267 #ifdef ROS_PACKAGE_NAME
00268 #define ROSCONSOLE_PACKAGE_NAME ROS_PACKAGE_NAME
00269 #else
00270 #define ROSCONSOLE_PACKAGE_NAME "unknown_package"
00271 #endif
00272
00273 #define ROSCONSOLE_ROOT_LOGGER_NAME "ros"
00274 #define ROSCONSOLE_NAME_PREFIX ROSCONSOLE_ROOT_LOGGER_NAME "." ROSCONSOLE_PACKAGE_NAME
00275 #define ROSCONSOLE_DEFAULT_NAME ROSCONSOLE_NAME_PREFIX
00276
00277
00278 #define ROSCONSOLE_SEVERITY_DEBUG 0
00279 #define ROSCONSOLE_SEVERITY_INFO 1
00280 #define ROSCONSOLE_SEVERITY_WARN 2
00281 #define ROSCONSOLE_SEVERITY_ERROR 3
00282 #define ROSCONSOLE_SEVERITY_FATAL 4
00283 #define ROSCONSOLE_SEVERITY_NONE 5
00284
00290 #ifndef ROSCONSOLE_MIN_SEVERITY
00291 #define ROSCONSOLE_MIN_SEVERITY ROSCONSOLE_SEVERITY_DEBUG
00292 #endif
00293
00298 #define ROSCONSOLE_AUTOINIT \
00299 do \
00300 { \
00301 if (ROS_UNLIKELY(!::ros::console::g_initialized)) \
00302 { \
00303 ::ros::console::initialize(); \
00304 } \
00305 } while(0)
00306
00307 #define ROSCONSOLE_DEFINE_LOCATION(cond, level, name) \
00308 ROSCONSOLE_AUTOINIT; \
00309 static ::ros::console::LogLocation loc = {false, false, ::ros::console::levels::Count, 0}; \
00310 if (ROS_UNLIKELY(!loc.initialized_)) \
00311 { \
00312 initializeLogLocation(&loc, name, level); \
00313 } \
00314 if (ROS_UNLIKELY(loc.level_ != level)) \
00315 { \
00316 setLogLocationLevel(&loc, level); \
00317 checkLogLocationEnabled(&loc); \
00318 } \
00319 bool enabled = loc.logger_enabled_ && (cond);
00320
00321 #define ROSCONSOLE_PRINT_AT_LOCATION_WITH_FILTER(filter, ...) \
00322 ::ros::console::print(filter, loc.logger_, loc.level_, __FILE__, __LINE__, __ROSCONSOLE_FUNCTION__, __VA_ARGS__)
00323
00324 #define ROSCONSOLE_PRINT_AT_LOCATION(...) \
00325 ROSCONSOLE_PRINT_AT_LOCATION_WITH_FILTER(0, __VA_ARGS__)
00326
00327
00328 #define ROSCONSOLE_PRINT_STREAM_AT_LOCATION_WITH_FILTER(filter, args) \
00329 do \
00330 { \
00331 std::stringstream __rosconsole_print_stream_at_location_with_filter__ss__; \
00332 __rosconsole_print_stream_at_location_with_filter__ss__ << args; \
00333 ::ros::console::print(filter, loc.logger_, loc.level_, __rosconsole_print_stream_at_location_with_filter__ss__, __FILE__, __LINE__, __ROSCONSOLE_FUNCTION__); \
00334 } while (0)
00335
00336 #define ROSCONSOLE_PRINT_STREAM_AT_LOCATION(args) \
00337 ROSCONSOLE_PRINT_STREAM_AT_LOCATION_WITH_FILTER(0, args)
00338
00348 #define ROS_LOG_COND(cond, level, name, ...) \
00349 do \
00350 { \
00351 ROSCONSOLE_DEFINE_LOCATION(cond, level, name); \
00352 \
00353 if (ROS_UNLIKELY(enabled)) \
00354 { \
00355 ROSCONSOLE_PRINT_AT_LOCATION(__VA_ARGS__); \
00356 } \
00357 } while(0)
00358
00368 #define ROS_LOG_STREAM_COND(cond, level, name, args) \
00369 do \
00370 { \
00371 ROSCONSOLE_DEFINE_LOCATION(cond, level, name); \
00372 if (ROS_UNLIKELY(enabled)) \
00373 { \
00374 ROSCONSOLE_PRINT_STREAM_AT_LOCATION(args); \
00375 } \
00376 } while(0)
00377
00384 #define ROS_LOG_ONCE(level, name, ...) \
00385 do \
00386 { \
00387 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \
00388 static bool hit = false; \
00389 if (ROS_UNLIKELY(enabled) && ROS_UNLIKELY(!hit)) \
00390 { \
00391 hit = true; \
00392 ROSCONSOLE_PRINT_AT_LOCATION(__VA_ARGS__); \
00393 } \
00394 } while(0)
00395
00396
00403 #define ROS_LOG_STREAM_ONCE(level, name, args) \
00404 do \
00405 { \
00406 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \
00407 static bool __ros_log_stream_once__hit__ = false; \
00408 if (ROS_UNLIKELY(enabled) && ROS_UNLIKELY(!__ros_log_stream_once__hit__)) \
00409 { \
00410 __ros_log_stream_once__hit__ = true; \
00411 ROSCONSOLE_PRINT_STREAM_AT_LOCATION(args); \
00412 } \
00413 } while(0)
00414
00422 #define ROS_LOG_THROTTLE(rate, level, name, ...) \
00423 do \
00424 { \
00425 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \
00426 static double last_hit = 0.0; \
00427 ::ros::Time now = ::ros::Time::now(); \
00428 if (ROS_UNLIKELY(enabled) && ROS_UNLIKELY(last_hit + rate <= now.toSec())) \
00429 { \
00430 last_hit = now.toSec(); \
00431 ROSCONSOLE_PRINT_AT_LOCATION(__VA_ARGS__); \
00432 } \
00433 } while(0)
00434
00435
00443 #define ROS_LOG_STREAM_THROTTLE(rate, level, name, args) \
00444 do \
00445 { \
00446 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \
00447 static double __ros_log_stream_throttle__last_hit__ = 0.0; \
00448 ::ros::Time __ros_log_stream_throttle__now__ = ::ros::Time::now(); \
00449 if (ROS_UNLIKELY(enabled) && ROS_UNLIKELY(__ros_log_stream_throttle__last_hit__ + rate <= __ros_log_stream_throttle__now__.toSec())) \
00450 { \
00451 __ros_log_stream_throttle__last_hit__ = __ros_log_stream_throttle__now__.toSec(); \
00452 ROSCONSOLE_PRINT_STREAM_AT_LOCATION(args); \
00453 } \
00454 } while(0)
00455
00463 #define ROS_LOG_FILTER(filter, level, name, ...) \
00464 do \
00465 { \
00466 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \
00467 if (ROS_UNLIKELY(enabled) && (filter)->isEnabled()) \
00468 { \
00469 ROSCONSOLE_PRINT_AT_LOCATION_WITH_FILTER(filter, __VA_ARGS__); \
00470 } \
00471 } while(0)
00472
00480 #define ROS_LOG_STREAM_FILTER(filter, level, name, args) \
00481 do \
00482 { \
00483 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \
00484 if (ROS_UNLIKELY(enabled) && (filter)->isEnabled()) \
00485 { \
00486 ROSCONSOLE_PRINT_STREAM_AT_LOCATION_WITH_FILTER(filter, args); \
00487 } \
00488 } while(0)
00489
00496 #define ROS_LOG(level, name, ...) ROS_LOG_COND(true, level, name, __VA_ARGS__)
00497
00503 #define ROS_LOG_STREAM(level, name, args) ROS_LOG_STREAM_COND(true, level, name, args)
00504
00505 #include "rosconsole/macros_generated.h"
00506
00507 #endif // ROSCONSOLE_ROSCONSOLE_H