32 #if defined(__APPLE__) && defined(__GNUC__) && defined(__llvm__) && !defined(__clang__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) 33 #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 41 #include <boost/thread.hpp> 42 #include <boost/shared_array.hpp> 43 #include <boost/regex.hpp> 44 #include <boost/make_shared.hpp> 63 #ifdef ROSCONSOLE_BACKEND_LOG4CXX 66 log4cxx::Level::getDebug(),
67 log4cxx::Level::getInfo(),
68 log4cxx::Level::getWarn(),
69 log4cxx::Level::getError(),
70 log4cxx::Level::getFatal(),
76 #define COLOR_NORMAL "" 78 #define COLOR_GREEN "" 79 #define COLOR_YELLOW "" 81 #define COLOR_NORMAL "\033[0m" 82 #define COLOR_RED "\033[31m" 83 #define COLOR_GREEN "\033[32m" 84 #define COLOR_YELLOW "\033[33m" 92 typedef std::map<std::string, std::string>
M_string;
97 g_extra_fixed_tokens[key] = val;
122 M_string::iterator it = g_extra_fixed_tokens.find(
str_);
123 if (it == g_extra_fixed_tokens.end())
125 return (
"${" +
str_ +
"}").c_str();
128 return it->second.c_str();
138 return "PLACEHOLDER";
187 std::stringstream ss;
201 std::stringstream ss;
211 std::stringstream ss;
212 ss << boost::this_thread::get_id();
250 std::stringstream ss;
258 if (type ==
"severity")
260 return TokenPtr(boost::make_shared<SeverityToken>());
262 else if (type ==
"message")
264 return TokenPtr(boost::make_shared<MessageToken>());
266 else if (type ==
"time")
268 return TokenPtr(boost::make_shared<TimeToken>());
270 else if (type ==
"walltime")
272 return TokenPtr(boost::make_shared<WallTimeToken>());
274 else if (type ==
"thread")
276 return TokenPtr(boost::make_shared<ThreadToken>());
278 else if (type ==
"logger")
280 return TokenPtr(boost::make_shared<LoggerToken>());
282 else if (type ==
"file")
284 return TokenPtr(boost::make_shared<FileToken>());
286 else if (type ==
"line")
288 return TokenPtr(boost::make_shared<LineToken>());
290 else if (type ==
"function")
292 return TokenPtr(boost::make_shared<FunctionToken>());
295 return TokenPtr(boost::make_shared<FixedMapToken>(type));
302 boost::regex e(
"\\$\\{([a-z|A-Z]+)\\}");
303 boost::match_results<std::string::const_iterator> results;
304 std::string::const_iterator start, end;
305 start = format_.begin();
307 bool matched_once =
false;
308 std::string last_suffix;
309 while (boost::regex_search(start, end, results, e))
312 for (
size_t i = 0; i < results.size(); ++i)
314 std::cout << i <<
"|" << results.prefix() <<
"|" << results[i] <<
"|" << results.suffix() << std::endl;
318 std::string token = results[1];
319 last_suffix = results.suffix();
320 tokens_.push_back(
TokenPtr(boost::make_shared<FixedToken>(results.prefix())));
323 start = results[0].second;
329 tokens_.push_back(
TokenPtr(boost::make_shared<FixedToken>(last_suffix)));
333 tokens_.push_back(
TokenPtr(boost::make_shared<FixedToken>(format_)));
366 std::stringstream ss;
371 V_Token::iterator it = tokens_.begin();
372 V_Token::iterator end = tokens_.end();
373 for (; it != end; ++it)
375 ss << (*it)->getString(logger_handle, level, str, file,
function, line);
382 fprintf(f,
"%s\n", ss.str().c_str());
384 if (g_force_stdout_line_buffered && f == stdout)
386 int flush_result = fflush(f);
387 if (flush_result != 0 && !g_stdout_flush_failure_reported)
389 g_stdout_flush_failure_reported =
true;
390 fprintf(stderr,
"Error: failed to perform fflush on stdout, fflush return code is %d\n", flush_result);
400 g_formatter.
print(logger_handle, level, str, file,
function, line);
405 boost::mutex::scoped_lock lock(g_init_mutex);
410 char* format_string = NULL;
412 _dupenv_s(&format_string, NULL,
"ROSCONSOLE_FORMAT");
414 format_string = getenv(
"ROSCONSOLE_FORMAT");
418 g_format_string = format_string;
421 g_formatter.
init(g_format_string);
425 std::string line_buffered;
428 if (line_buffered ==
"1")
430 g_force_stdout_line_buffered =
true;
432 else if (line_buffered !=
"0")
434 fprintf(stderr,
"Warning: unexpected value %s specified for ROSCONSOLE_STDOUT_LINE_BUFFERED. Default value 0 " 435 "will be used. Valid values are 1 or 0.\n", line_buffered.c_str());
439 std::string no_color;
446 g_initialized =
true;
453 va_copy(arg_copy, args);
454 size_t total = vsnprintf(buffer.get(), buffer_size, fmt, args);
455 if (total >= buffer_size)
457 buffer_size = total + 1;
458 buffer.reset(
new char[buffer_size]);
459 vsnprintf(buffer.get(), buffer_size, fmt, arg_copy);
486 return std::string(buffer.get(), size);
489 #define INITIAL_BUFFER_SIZE 4096 495 const char* file,
int line,
const char*
function,
const char* fmt, ...)
500 if (g_printing_thread_id == boost::this_thread::get_id())
502 fprintf(stderr,
"Warning: recursive print statement has occurred. Throwing out recursive print.\n");
506 boost::mutex::scoped_lock lock(g_print_mutex);
508 g_printing_thread_id = boost::this_thread::get_id();
525 params.
level = level;
526 params.
logger = logger_handle;
529 level = params.
level;
534 if (g_print_buffer_size <= msg_size)
536 g_print_buffer_size = msg_size + 1;
554 catch (std::exception& e)
556 fprintf(stderr,
"Caught exception while logging: [%s]\n", e.what());
560 g_printing_thread_id = boost::thread::id();
564 const std::stringstream& ss,
const char* file,
int line,
const char*
function)
569 if (g_printing_thread_id == boost::this_thread::get_id())
571 fprintf(stderr,
"Warning: recursive print statement has occurred. Throwing out recursive print.\n");
575 boost::mutex::scoped_lock lock(g_print_mutex);
577 g_printing_thread_id = boost::this_thread::get_id();
580 std::string str = ss.str();
588 params.
level = level;
589 params.
logger = logger_handle;
592 level = params.
level;
604 g_last_error_message = str;
610 catch (std::exception& e)
612 fprintf(stderr,
"Caught exception while logging: [%s]\n", e.what());
616 g_printing_thread_id = boost::thread::id();
624 boost::mutex::scoped_lock lock(g_locations_mutex);
626 g_log_locations.push_back(loc);
636 boost::mutex::scoped_lock lock(g_locations_mutex);
646 g_log_locations.push_back(loc);
655 boost::mutex::scoped_lock lock(g_locations_mutex);
661 boost::mutex::scoped_lock lock(g_locations_mutex);
667 boost::mutex::scoped_lock lock(g_locations_mutex);
669 V_LogLocation::iterator it = g_log_locations.begin();
670 V_LogLocation::iterator end = g_log_locations.end();
671 for ( ; it != end; ++it )
701 g_shutting_down =
true;
virtual std::string getString(void *, ::ros::console::Level, const char *str, const char *, const char *, int)
ROSCONSOLE_BACKEND_DECL void(* function_print)(void *, ::ros::console::Level, const char *, const char *, const char *, int)
V_LogLocation g_log_locations
ROSCONSOLE_DECL void registerLogLocation(LogLocation *loc)
Registers a logging location with the system.
virtual std::string getString(void *, ::ros::console::Level, const char *, const char *, const char *function, int)
static boost::mutex g_print_mutex
log4cxx::LevelPtr g_level_lookup[levels::Count]
virtual bool isEnabled()
Returns whether or not the log statement should be printed. Called before the log arguments are evalu...
M_string g_extra_fixed_tokens
ROSCONSOLE_DECL void notifyLoggerLevelsChanged()
Tells the system that a logger's level has changed.
Base-class for filters. Filters allow full user-defined control over whether or not a message should ...
const char * g_format_string
Parameter structure passed to FilterBase::isEnabled(...);. Includes both input and output parameters...
::ros::console::Level level_
TokenPtr createTokenFromType(const std::string &type)
ROSCONSOLE_DECL void initialize()
Don't call this directly. Performs any required initialization/configuration. Happens automatically w...
void * logger
[input/output] Handle identifying logger that this message will be output to. If changed, uses the new logger
virtual std::string getString(void *, ::ros::console::Level level, const char *str, const char *file, const char *function, int line)
ROSCONSOLE_DECL void setFixedFilterToken(const std::string &key, const std::string &val)
ROSCONSOLE_CONSOLE_IMPL_DECL void shutdown()
void _print(void *logger_handle, ::ros::console::Level level, const char *str, const char *file, const char *function, int line)
ROSCONSOLE_CONSOLE_IMPL_DECL std::string getName(void *handle)
std::vector< LogLocation * > V_LogLocation
ROSCONSOLE_DECL bool get_loggers(std::map< std::string, levels::Level > &loggers)
const char * message
[input] The formatted message that will be output
#define ROSCONSOLE_AUTOINIT
Initializes the rosconsole library. Usually unnecessary to call directly.
virtual std::string getString(void *, ::ros::console::Level, const char *, const char *, const char *, int line)
ROSCONSOLE_DECL bool g_initialized
Only exported because the macros need it. Do not use directly.
ROSCONSOLE_DECL std::string formatToString(const char *fmt,...)
ROSCONSOLE_BACKEND_DECL void(* function_notifyLoggerLevelsChanged)()
ROSCONSOLE_DECL void print(FilterBase *filter, void *logger, Level level, const char *file, int line, const char *function, const char *fmt,...) ROSCONSOLE_PRINTF_ATTRIBUTE(7
Don't call this directly. Use the ROS_LOG() macro instead.
ROSCONSOLE_DECL void checkLogLocationEnabled(LogLocation *loc)
Internal.
ROSCONSOLE_DECL void deregister_appender(LogAppender *appender)
std::string out_message
[output] If set, writes this message instead of the original
ROSCONSOLE_CONSOLE_IMPL_DECL void register_appender(LogAppender *appender)
boost::shared_ptr< Token > TokenPtr
Level level
[input/output] Severity level. If changed, uses the new level
ROSCONSOLE_CONSOLE_IMPL_DECL bool get_loggers(std::map< std::string, levels::Level > &loggers)
virtual std::string getString(void *, ::ros::console::Level, const char *, const char *, const char *, int)
bool g_force_stdout_line_buffered
std::map< std::string, std::string > M_string
ROSCONSOLE_DECL void vformatToBuffer(boost::shared_array< char > &buffer, size_t &buffer_size, const char *fmt, va_list args)
FixedMapToken(const std::string &str)
const char * file
[input] File the message came from
ROSCONSOLE_CONSOLE_IMPL_DECL bool set_logger_level(const std::string &name, levels::Level level)
const char * function
[input] Function the message came from
virtual std::string getString(void *, ::ros::console::Level, const char *, const char *file, const char *, int)
ROSCONSOLE_CONSOLE_IMPL_DECL bool isEnabledFor(void *handle, ::ros::console::Level level)
bool get_environment_variable(std::string &str, const char *environment_variable)
virtual std::string getString(void *, ::ros::console::Level, const char *, const char *, const char *, int)
#define INITIAL_BUFFER_SIZE
ROSCONSOLE_CONSOLE_IMPL_DECL void deregister_appender(LogAppender *appender)
ROSCONSOLE_DECL void initializeLogLocation(LogLocation *loc, const std::string &name, Level level)
Internal.
virtual std::string getString(void *, ::ros::console::Level, const char *, const char *, const char *, int)
static size_t g_print_buffer_size
static boost::thread::id g_printing_thread_id
virtual std::string getString(void *logger_handle, ::ros::console::Level level, const char *str, const char *file, const char *function, int line)
void checkLogLocationEnabledNoLock(LogLocation *loc)
ROSCONSOLE_DECL void shutdown()
boost::mutex g_init_mutex
virtual std::string getString(void *, ::ros::console::Level, const char *, const char *, const char *, int)
int line
[input] Line the message came from
static boost::shared_array< char > g_print_buffer(new char[INITIAL_BUFFER_SIZE])
virtual std::string getString(void *, ::ros::console::Level, const char *, const char *, const char *, int)
ROSCONSOLE_CONSOLE_IMPL_DECL void * getHandle(const std::string &name)
boost::mutex g_locations_mutex
ROSCONSOLE_DECL std::string g_last_error_message
Only exported because the TopicManager need it. Do not use directly.
ROSCONSOLE_DECL bool set_logger_level(const std::string &name, levels::Level level)
ROSCONSOLE_DECL Formatter g_formatter
Only exported because the implementation need it. Do not use directly.
ROSCONSOLE_DECL void setLogLocationLevel(LogLocation *loc, Level level)
Internal.
ROSCONSOLE_DECL void register_appender(LogAppender *appender)
FixedToken(const std::string &str)
void print(ros::console::Level level, const std::string &s)
ROSCONSOLE_DECL void formatToBuffer(boost::shared_array< char > &buffer, size_t &buffer_size, const char *fmt,...)
bool g_stdout_flush_failure_reported
virtual std::string getString(void *, ::ros::console::Level, const char *, const char *, const char *, int)