$search
00001 /* 00002 * Copyright (c) 2008, Willow Garage, Inc. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of Willow Garage, Inc. nor the names of its 00014 * contributors may be used to endorse or promote products derived from 00015 * this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 // Author: Josh Faust 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 // Import/export for windows dll's and visibility for gcc shared libraries. 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 // TODO: this header is no longer needed to be included here, but removing it will break various code that incorrectly does not itself include log4cxx/logger.h 00054 // We should vet all the code using log4cxx directly and make sure the includes/link flags are used in those packages, and then we can remove this include 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 // log4cxx forward declarations 00068 namespace log4cxx 00069 { 00070 namespace helpers 00071 { 00072 template<typename T> class ObjectPtrT; 00073 } // namespace helpers 00074 00075 class Level; 00076 typedef helpers::ObjectPtrT<Level> LevelPtr; 00077 00078 class Logger; 00079 typedef helpers::ObjectPtrT<Logger> LoggerPtr; 00080 } // namespace log4cxx 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 // input parameters 00168 const char* file; 00169 int line; 00170 const char* function; 00171 const char* message; 00172 00173 // input/output parameters 00174 log4cxx::LoggerPtr logger; 00175 Level level; 00176 00177 // output parameters 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 } // namespace console 00248 } // namespace ros 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 // These allow you to compile-out everything below a certain severity level if necessary 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}; /* Initialized at compile-time */ \ 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 #define ROSCONSOLE_PRINT_STREAM_AT_LOCATION_WITH_FILTER(filter, args) \ 00328 do \ 00329 { \ 00330 std::stringstream ss; \ 00331 ss << args; \ 00332 ::ros::console::print(filter, loc.logger_, loc.level_, ss, __FILE__, __LINE__, __ROSCONSOLE_FUNCTION__); \ 00333 } while (0) 00334 00335 #define ROSCONSOLE_PRINT_STREAM_AT_LOCATION(args) \ 00336 ROSCONSOLE_PRINT_STREAM_AT_LOCATION_WITH_FILTER(0, args) 00337 00347 #define ROS_LOG_COND(cond, level, name, ...) \ 00348 do \ 00349 { \ 00350 ROSCONSOLE_DEFINE_LOCATION(cond, level, name); \ 00351 \ 00352 if (ROS_UNLIKELY(enabled)) \ 00353 { \ 00354 ROSCONSOLE_PRINT_AT_LOCATION(__VA_ARGS__); \ 00355 } \ 00356 } while(0) 00357 00367 #define ROS_LOG_STREAM_COND(cond, level, name, args) \ 00368 do \ 00369 { \ 00370 ROSCONSOLE_DEFINE_LOCATION(cond, level, name); \ 00371 if (ROS_UNLIKELY(enabled)) \ 00372 { \ 00373 ROSCONSOLE_PRINT_STREAM_AT_LOCATION(args); \ 00374 } \ 00375 } while(0) 00376 00383 #define ROS_LOG_ONCE(level, name, ...) \ 00384 do \ 00385 { \ 00386 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \ 00387 static bool hit = false; \ 00388 if (ROS_UNLIKELY(enabled) && ROS_UNLIKELY(!hit)) \ 00389 { \ 00390 hit = true; \ 00391 ROSCONSOLE_PRINT_AT_LOCATION(__VA_ARGS__); \ 00392 } \ 00393 } while(0) 00394 00401 #define ROS_LOG_STREAM_ONCE(level, name, args) \ 00402 do \ 00403 { \ 00404 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \ 00405 static bool hit = false; \ 00406 if (ROS_UNLIKELY(enabled) && ROS_UNLIKELY(!hit)) \ 00407 { \ 00408 hit = true; \ 00409 ROSCONSOLE_PRINT_STREAM_AT_LOCATION(args); \ 00410 } \ 00411 } while(0) 00412 00420 #define ROS_LOG_THROTTLE(rate, level, name, ...) \ 00421 do \ 00422 { \ 00423 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \ 00424 static double last_hit = 0.0; \ 00425 ::ros::Time now = ::ros::Time::now(); \ 00426 if (ROS_UNLIKELY(enabled) && ROS_UNLIKELY(last_hit + rate <= now.toSec())) \ 00427 { \ 00428 last_hit = now.toSec(); \ 00429 ROSCONSOLE_PRINT_AT_LOCATION(__VA_ARGS__); \ 00430 } \ 00431 } while(0) 00432 00440 #define ROS_LOG_STREAM_THROTTLE(rate, level, name, args) \ 00441 do \ 00442 { \ 00443 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \ 00444 static double last_hit = 0.0; \ 00445 ::ros::Time now = ::ros::Time::now(); \ 00446 if (ROS_UNLIKELY(enabled) && ROS_UNLIKELY(last_hit + rate <= now.toSec())) \ 00447 { \ 00448 last_hit = now.toSec(); \ 00449 ROSCONSOLE_PRINT_STREAM_AT_LOCATION(args); \ 00450 } \ 00451 } while(0) 00452 00460 #define ROS_LOG_FILTER(filter, level, name, ...) \ 00461 do \ 00462 { \ 00463 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \ 00464 if (ROS_UNLIKELY(enabled) && (filter)->isEnabled()) \ 00465 { \ 00466 ROSCONSOLE_PRINT_AT_LOCATION_WITH_FILTER(filter, __VA_ARGS__); \ 00467 } \ 00468 } while(0) 00469 00477 #define ROS_LOG_STREAM_FILTER(filter, level, name, args) \ 00478 do \ 00479 { \ 00480 ROSCONSOLE_DEFINE_LOCATION(true, level, name); \ 00481 if (ROS_UNLIKELY(enabled) && (filter)->isEnabled()) \ 00482 { \ 00483 ROSCONSOLE_PRINT_STREAM_AT_LOCATION_WITH_FILTER(filter, args); \ 00484 } \ 00485 } while(0) 00486 00493 #define ROS_LOG(level, name, ...) ROS_LOG_COND(true, level, name, __VA_ARGS__) 00494 00500 #define ROS_LOG_STREAM(level, name, args) ROS_LOG_STREAM_COND(true, level, name, args) 00501 00502 #include "rosconsole/macros_generated.h" 00503 00504 #endif // ROSCONSOLE_ROSCONSOLE_H