Go to the documentation of this file.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 #if defined(__APPLE__) && defined(__GNUC__) && defined(__llvm__) && !defined(__clang__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2)
00033 #error This code is known to provoke a compiler crash with llvm-gcc 4.2. You will have better luck with clang++. See code.ros.org/trac/ros/ticket/3626
00034 #endif
00035
00036 #include "ros/console.h"
00037 #include "ros/assert.h"
00038 #include <ros/time.h>
00039 #include "log4cxx/appenderskeleton.h"
00040 #include "log4cxx/spi/loggingevent.h"
00041 #include "log4cxx/level.h"
00042 #include "log4cxx/propertyconfigurator.h"
00043 #ifdef _MSC_VER
00044
00045 #include "log4cxx/helpers/transcoder.h"
00046 #endif
00047
00048 #include <boost/thread.hpp>
00049 #include <boost/shared_array.hpp>
00050 #include <boost/regex.hpp>
00051
00052 #include <cstdarg>
00053 #include <cstdlib>
00054 #include <cstdio>
00055 #include <memory>
00056 #include <cstring>
00057 #include <stdexcept>
00058
00059 namespace ros
00060 {
00061 namespace console
00062 {
00063 namespace impl
00064 {
00065
00066 log4cxx::LevelPtr g_level_lookup[ levels::Count ] =
00067 {
00068 log4cxx::Level::getDebug(),
00069 log4cxx::Level::getInfo(),
00070 log4cxx::Level::getWarn(),
00071 log4cxx::Level::getError(),
00072 log4cxx::Level::getFatal(),
00073 };
00074
00075
00076 class ROSConsoleStdioAppender : public log4cxx::AppenderSkeleton
00077 {
00078 public:
00079 ~ROSConsoleStdioAppender()
00080 {
00081 }
00082
00083 protected:
00084 virtual void append(const log4cxx::spi::LoggingEventPtr& event,
00085 log4cxx::helpers::Pool&)
00086 {
00087 levels::Level level = levels::Count;
00088 if (event->getLevel() == log4cxx::Level::getDebug())
00089 {
00090 level = levels::Debug;
00091 }
00092 else if (event->getLevel() == log4cxx::Level::getInfo())
00093 {
00094 level = levels::Info;
00095 }
00096 else if (event->getLevel() == log4cxx::Level::getWarn())
00097 {
00098 level = levels::Warn;
00099 }
00100 else if (event->getLevel() == log4cxx::Level::getError())
00101 {
00102 level = levels::Error;
00103 }
00104 else if (event->getLevel() == log4cxx::Level::getFatal())
00105 {
00106 level = levels::Fatal;
00107 }
00108 #ifdef _MSC_VER
00109 LOG4CXX_ENCODE_CHAR(tmpstr, event->getMessage());
00110 std::string msg = tmpstr
00111 #else
00112 std::string msg = event->getMessage();
00113 #endif
00114 const log4cxx::spi::LocationInfo& location_info = event->getLocationInformation();
00115 ::ros::console::backend::print(event.operator->(), level, msg.c_str(), location_info.getFileName(), location_info.getMethodName().c_str(), location_info.getLineNumber());
00116 }
00117
00118 virtual void close()
00119 {
00120 }
00121 virtual bool requiresLayout() const
00122 {
00123 return false;
00124 }
00125 };
00126
00127 void initialize()
00128 {
00129
00130 log4cxx::LoggerPtr ros_logger = log4cxx::Logger::getLogger(ROSCONSOLE_ROOT_LOGGER_NAME);
00131 ros_logger->setLevel(log4cxx::Level::getInfo());
00132
00133 log4cxx::LoggerPtr roscpp_superdebug = log4cxx::Logger::getLogger("ros.roscpp.superdebug");
00134 roscpp_superdebug->setLevel(log4cxx::Level::getWarn());
00135
00136
00137 char* ros_root_cstr = NULL;
00138 #ifdef _MSC_VER
00139 _dupenv_s(&ros_root_cstr, NULL, "ROS_ROOT");
00140 #else
00141 ros_root_cstr = getenv("ROS_ROOT");
00142 #endif
00143 if (ros_root_cstr)
00144 {
00145 std::string config_file = std::string(ros_root_cstr) + "/config/rosconsole.config";
00146 FILE* config_file_ptr = fopen( config_file.c_str(), "r" );
00147 if( config_file_ptr )
00148 {
00149 fclose( config_file_ptr );
00150 log4cxx::PropertyConfigurator::configure(config_file);
00151 }
00152 }
00153 char* config_file_cstr = NULL;
00154 #ifdef _MSC_VER
00155 _dupenv_s(&config_file_cstr, NULL, "ROSCONSOLE_CONFIG_FILE");
00156 #else
00157 config_file_cstr = getenv("ROSCONSOLE_CONFIG_FILE");
00158 #endif
00159 if ( config_file_cstr )
00160 {
00161 std::string config_file = config_file_cstr;
00162 log4cxx::PropertyConfigurator::configure(config_file);
00163 }
00164
00165 log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(ROSCONSOLE_ROOT_LOGGER_NAME);
00166 logger->addAppender(new ROSConsoleStdioAppender);
00167 #ifdef _MSC_VER
00168 if ( ros_root_cstr != NULL ) {
00169 free(ros_root_cstr);
00170 }
00171 if ( config_file_cstr != NULL ) {
00172 free(config_file_cstr);
00173 }
00174 if ( format_string != NULL ) {
00175 free(format_string);
00176 }
00177
00178 #endif
00179 }
00180
00181
00182 void print(void* handle, ::ros::console::Level level, const char* str, const char* file, const char* function, int line)
00183 {
00184 log4cxx::Logger* logger = (log4cxx::Logger*)handle;
00185 try
00186 {
00187 logger->forcedLog(g_level_lookup[level], str, log4cxx::spi::LocationInfo(file, function, line));
00188 }
00189 catch (std::exception& e)
00190 {
00191 fprintf(stderr, "Caught exception while logging: [%s]\n", e.what());
00192 }
00193 }
00194
00195 bool isEnabledFor(void* handle, ::ros::console::Level level)
00196 {
00197 log4cxx::Logger* logger = (log4cxx::Logger*)handle;
00198 return logger->isEnabledFor(g_level_lookup[level]);
00199 }
00200
00201 void* getHandle(const std::string& name)
00202 {
00203 return log4cxx::Logger::getLogger(name);
00204 }
00205
00206 std::string getName(void* handle)
00207 {
00208 const log4cxx::spi::LoggingEvent* event = (const log4cxx::spi::LoggingEvent*)handle;
00209 #ifdef _MSC_VER
00210 LOG4CXX_ENCODE_CHAR(tmpstr, event->getLoggerName());
00211 return tmpstr
00212 #else
00213 return event->getLoggerName();
00214 #endif
00215 }
00216
00217 bool get_loggers(std::map<std::string, levels::Level>& loggers)
00218 {
00219 log4cxx::spi::LoggerRepositoryPtr repo = log4cxx::Logger::getLogger(ROSCONSOLE_ROOT_LOGGER_NAME)->getLoggerRepository();
00220
00221 log4cxx::LoggerList current_loggers = repo->getCurrentLoggers();
00222 log4cxx::LoggerList::iterator it = current_loggers.begin();
00223 log4cxx::LoggerList::iterator end = current_loggers.end();
00224 for (; it != end; ++it)
00225 {
00226 std::string name;
00227 #ifdef _MSC_VER
00228 LOG4CXX_ENCODE_CHAR(name, (*it)->getName());
00229 #else
00230 name = (*it)->getName();
00231 #endif
00232
00233 const log4cxx::LevelPtr& log4cxx_level = (*it)->getEffectiveLevel();
00234 levels::Level level;
00235 if (log4cxx_level == log4cxx::Level::getDebug())
00236 {
00237 level = levels::Debug;
00238 }
00239 else if (log4cxx_level == log4cxx::Level::getInfo())
00240 {
00241 level = levels::Info;
00242 }
00243 else if (log4cxx_level == log4cxx::Level::getWarn())
00244 {
00245 level = levels::Warn;
00246 }
00247 else if (log4cxx_level == log4cxx::Level::getError())
00248 {
00249 level = levels::Error;
00250 }
00251 else if (log4cxx_level == log4cxx::Level::getFatal())
00252 {
00253 level = levels::Fatal;
00254 }
00255 else
00256 {
00257 return false;
00258 }
00259 loggers[name] = level;
00260 }
00261
00262 return true;
00263 }
00264
00265 bool set_logger_level(const std::string& name, levels::Level level)
00266 {
00267 log4cxx::LevelPtr log4cxx_level;
00268 if (level == levels::Debug)
00269 {
00270 log4cxx_level = log4cxx::Level::getDebug();
00271 }
00272 else if (level == levels::Info)
00273 {
00274 log4cxx_level = log4cxx::Level::getInfo();
00275 }
00276 else if (level == levels::Warn)
00277 {
00278 log4cxx_level = log4cxx::Level::getWarn();
00279 }
00280 else if (level == levels::Error)
00281 {
00282 log4cxx_level = log4cxx::Level::getError();
00283 }
00284 else if (level == levels::Fatal)
00285 {
00286 log4cxx_level = log4cxx::Level::getFatal();
00287 }
00288 else
00289 {
00290 return false;
00291 }
00292
00293 log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(name);
00294 logger->setLevel(log4cxx_level);
00295 ::ros::console::backend::notifyLoggerLevelsChanged();
00296 return true;
00297 }
00298
00299 class Log4cxxAppender : public log4cxx::AppenderSkeleton
00300 {
00301 public:
00302 Log4cxxAppender(ros::console::LogAppender* appender) : appender_(appender) {}
00303 ~Log4cxxAppender() {}
00304
00305 protected:
00306 virtual void append(const log4cxx::spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool)
00307 {
00308 (void)pool;
00309 levels::Level level;
00310 if (event->getLevel() == log4cxx::Level::getFatal())
00311 {
00312 level = levels::Fatal;
00313 }
00314 else if (event->getLevel() == log4cxx::Level::getError())
00315 {
00316 level = levels::Error;
00317 }
00318 else if (event->getLevel() == log4cxx::Level::getWarn())
00319 {
00320 level = levels::Warn;
00321 }
00322 else if (event->getLevel() == log4cxx::Level::getInfo())
00323 {
00324 level = levels::Info;
00325 }
00326 else if (event->getLevel() == log4cxx::Level::getDebug())
00327 {
00328 level = levels::Debug;
00329 }
00330 else
00331 {
00332 return;
00333 }
00334
00335 #ifdef _MSC_VER
00336 LOG4CXX_ENCODE_CHAR(tmpstr, event->getMessage());
00337 std::string msg = tmpstr
00338 #else
00339 std::string msg = event->getMessage();
00340 #endif
00341
00342 const log4cxx::spi::LocationInfo& info = event->getLocationInformation();
00343 appender_->log(level, msg.c_str(), info.getFileName(), info.getMethodName().c_str(), info.getLineNumber());
00344 }
00345
00346 virtual void close() {}
00347 virtual bool requiresLayout() const { return false; }
00348 ros::console::LogAppender* appender_;
00349 };
00350
00351 Log4cxxAppender* g_log4cxx_appender;
00352
00353 void register_appender(LogAppender* appender)
00354 {
00355 g_log4cxx_appender = new Log4cxxAppender(appender);
00356 const log4cxx::LoggerPtr& logger = log4cxx::Logger::getLogger(ROSCONSOLE_ROOT_LOGGER_NAME);
00357 logger->addAppender(g_log4cxx_appender);
00358 }
00359
00360 void shutdown()
00361 {
00362 const log4cxx::LoggerPtr& logger = log4cxx::Logger::getLogger(ROSCONSOLE_ROOT_LOGGER_NAME);
00363 logger->removeAppender(g_log4cxx_appender);
00364 g_log4cxx_appender = 0;
00365
00366
00367
00368
00369
00370 log4cxx::Logger::getRootLogger()->getLoggerRepository()->shutdown();
00371 }
00372
00373 }
00374 }
00375 }