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 loggers[name] = level;
00256 }
00257
00258 return true;
00259 }
00260
00261 bool set_logger_level(const std::string& name, levels::Level level)
00262 {
00263 log4cxx::LevelPtr log4cxx_level;
00264 if (level == levels::Debug)
00265 {
00266 log4cxx_level = log4cxx::Level::getDebug();
00267 }
00268 else if (level == levels::Info)
00269 {
00270 log4cxx_level = log4cxx::Level::getInfo();
00271 }
00272 else if (level == levels::Warn)
00273 {
00274 log4cxx_level = log4cxx::Level::getWarn();
00275 }
00276 else if (level == levels::Error)
00277 {
00278 log4cxx_level = log4cxx::Level::getError();
00279 }
00280 else if (level == levels::Fatal)
00281 {
00282 log4cxx_level = log4cxx::Level::getFatal();
00283 }
00284 else
00285 {
00286 return false;
00287 }
00288
00289 log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(name);
00290 logger->setLevel(log4cxx_level);
00291 ::ros::console::backend::notifyLoggerLevelsChanged();
00292 return true;
00293 }
00294
00295 class Log4cxxAppender : public log4cxx::AppenderSkeleton
00296 {
00297 public:
00298 Log4cxxAppender(ros::console::LogAppender* appender) : appender_(appender) {}
00299 ~Log4cxxAppender() {}
00300
00301 protected:
00302 virtual void append(const log4cxx::spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool)
00303 {
00304 levels::Level level;
00305 if (event->getLevel() == log4cxx::Level::getFatal())
00306 {
00307 level = levels::Fatal;
00308 }
00309 else if (event->getLevel() == log4cxx::Level::getError())
00310 {
00311 level = levels::Error;
00312 }
00313 else if (event->getLevel() == log4cxx::Level::getWarn())
00314 {
00315 level = levels::Warn;
00316 }
00317 else if (event->getLevel() == log4cxx::Level::getInfo())
00318 {
00319 level = levels::Info;
00320 }
00321 else if (event->getLevel() == log4cxx::Level::getDebug())
00322 {
00323 level = levels::Debug;
00324 }
00325 else
00326 {
00327 return;
00328 }
00329
00330 #ifdef _MSC_VER
00331 LOG4CXX_ENCODE_CHAR(tmpstr, event->getMessage());
00332 std::string msg = tmpstr
00333 #else
00334 std::string msg = event->getMessage();
00335 #endif
00336
00337 const log4cxx::spi::LocationInfo& info = event->getLocationInformation();
00338 appender_->log(level, msg.c_str(), info.getFileName(), info.getMethodName().c_str(), info.getLineNumber());
00339 }
00340
00341 virtual void close() {}
00342 virtual bool requiresLayout() const { return false; }
00343 ros::console::LogAppender* appender_;
00344 };
00345
00346 Log4cxxAppender* g_log4cxx_appender;
00347
00348 void register_appender(LogAppender* appender)
00349 {
00350 g_log4cxx_appender = new Log4cxxAppender(appender);
00351 const log4cxx::LoggerPtr& logger = log4cxx::Logger::getLogger(ROSCONSOLE_ROOT_LOGGER_NAME);
00352 logger->addAppender(g_log4cxx_appender);
00353 }
00354
00355 void shutdown()
00356 {
00357 const log4cxx::LoggerPtr& logger = log4cxx::Logger::getLogger(ROSCONSOLE_ROOT_LOGGER_NAME);
00358 logger->removeAppender(g_log4cxx_appender);
00359 g_log4cxx_appender = 0;
00360
00361
00362
00363
00364
00365 log4cxx::Logger::getRootLogger()->getLoggerRepository()->shutdown();
00366 }
00367
00368 }
00369 }
00370 }