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 40 #include <boost/thread.hpp> 41 #include <boost/shared_array.hpp> 42 #include <boost/regex.hpp> 43 #include <boost/make_shared.hpp> 66 void print(
void* handle, ::
ros::console::Level level,
const char* str,
const char* file,
const char*
function,
int line);
72 std::string
getName(
void* handle);
74 bool get_loggers(std::map<std::string, levels::Level>& loggers);
85 #ifdef ROSCONSOLE_BACKEND_LOG4CXX 88 log4cxx::Level::getDebug(),
89 log4cxx::Level::getInfo(),
90 log4cxx::Level::getWarn(),
91 log4cxx::Level::getError(),
92 log4cxx::Level::getFatal(),
98 #define COLOR_NORMAL "" 100 #define COLOR_GREEN "" 101 #define COLOR_YELLOW "" 103 #define COLOR_NORMAL "\033[0m" 104 #define COLOR_RED "\033[31m" 105 #define COLOR_GREEN "\033[32m" 106 #define COLOR_YELLOW "\033[33m" 113 typedef std::map<std::string, std::string>
M_string;
118 g_extra_fixed_tokens[key] = val;
143 M_string::iterator it = g_extra_fixed_tokens.find(str_);
144 if (it == g_extra_fixed_tokens.end())
146 return (
"${" + str_ +
"}").c_str();
149 return it->second.c_str();
159 return "PLACEHOLDER";
208 std::stringstream ss;
222 std::stringstream ss;
232 std::stringstream ss;
233 ss << boost::this_thread::get_id();
271 std::stringstream ss;
279 if (type ==
"severity")
281 return TokenPtr(boost::make_shared<SeverityToken>());
283 else if (type ==
"message")
285 return TokenPtr(boost::make_shared<MessageToken>());
287 else if (type ==
"time")
289 return TokenPtr(boost::make_shared<TimeToken>());
291 else if (type ==
"walltime")
293 return TokenPtr(boost::make_shared<WallTimeToken>());
295 else if (type ==
"thread")
297 return TokenPtr(boost::make_shared<ThreadToken>());
299 else if (type ==
"logger")
301 return TokenPtr(boost::make_shared<LoggerToken>());
303 else if (type ==
"file")
305 return TokenPtr(boost::make_shared<FileToken>());
307 else if (type ==
"line")
309 return TokenPtr(boost::make_shared<LineToken>());
311 else if (type ==
"function")
313 return TokenPtr(boost::make_shared<FunctionToken>());
316 return TokenPtr(boost::make_shared<FixedMapToken>(type));
323 boost::regex e(
"\\$\\{([a-z|A-Z]+)\\}");
324 boost::match_results<std::string::const_iterator> results;
325 std::string::const_iterator start, end;
326 start = format_.begin();
328 bool matched_once =
false;
329 std::string last_suffix;
330 while (boost::regex_search(start, end, results, e))
333 for (
size_t i = 0; i < results.size(); ++i)
335 std::cout << i <<
"|" << results.prefix() <<
"|" << results[i] <<
"|" << results.suffix() << std::endl;
339 std::string token = results[1];
340 last_suffix = results.suffix();
341 tokens_.push_back(
TokenPtr(boost::make_shared<FixedToken>(results.prefix())));
344 start = results[0].second;
350 tokens_.push_back(
TokenPtr(boost::make_shared<FixedToken>(last_suffix)));
354 tokens_.push_back(
TokenPtr(boost::make_shared<FixedToken>(format_)));
360 const char* color = NULL;
388 std::stringstream ss;
390 V_Token::iterator it = tokens_.begin();
391 V_Token::iterator end = tokens_.end();
392 for (; it != end; ++it)
394 ss << (*it)->getString(logger_handle, level, str, file,
function, line);
398 fprintf(f,
"%s\n", ss.str().c_str());
400 if (g_force_stdout_line_buffered && f == stdout)
402 int flush_result = fflush(f);
403 if (flush_result != 0 && !g_stdout_flush_failure_reported)
405 g_stdout_flush_failure_reported =
true;
406 fprintf(stderr,
"Error: failed to perform fflush on stdout, fflush return code is %d\n", flush_result);
416 g_formatter.
print(logger_handle, level, str, file,
function, line);
421 boost::mutex::scoped_lock lock(g_init_mutex);
426 char* format_string = NULL;
428 _dupenv_s(&format_string, NULL,
"ROSCONSOLE_FORMAT");
430 format_string = getenv(
"ROSCONSOLE_FORMAT");
434 g_format_string = format_string;
437 g_formatter.
init(g_format_string);
441 std::string line_buffered;
444 if (line_buffered ==
"1")
446 g_force_stdout_line_buffered =
true;
448 else if (line_buffered !=
"0")
450 fprintf(stderr,
"Warning: unexpected value %s specified for ROSCONSOLE_STDOUT_LINE_BUFFERED. Default value 0 " 451 "will be used. Valid values are 1 or 0.\n", line_buffered.c_str());
456 g_initialized =
true;
463 va_list arg_copy = args;
466 va_copy(arg_copy, args);
469 size_t total = vsnprintf_s(buffer.get(), buffer_size, buffer_size, fmt, args);
471 size_t total = vsnprintf(buffer.get(), buffer_size, fmt, args);
473 if (total >= buffer_size)
475 buffer_size = total + 1;
476 buffer.reset(
new char[buffer_size]);
479 vsnprintf_s(buffer.get(), buffer_size, buffer_size, fmt, arg_copy);
481 vsnprintf(buffer.get(), buffer_size, fmt, arg_copy);
509 return std::string(buffer.get(), size);
512 #define INITIAL_BUFFER_SIZE 4096 518 const char* file,
int line,
const char*
function,
const char* fmt, ...)
523 if (g_printing_thread_id == boost::this_thread::get_id())
525 fprintf(stderr,
"Warning: recursive print statement has occurred. Throwing out recursive print.\n");
529 boost::mutex::scoped_lock lock(g_print_mutex);
531 g_printing_thread_id = boost::this_thread::get_id();
548 params.
level = level;
549 params.
logger = logger_handle;
552 level = params.
level;
557 if (g_print_buffer_size <= msg_size)
559 g_print_buffer_size = msg_size + 1;
577 catch (std::exception& e)
579 fprintf(stderr,
"Caught exception while logging: [%s]\n", e.what());
583 g_printing_thread_id = boost::thread::id();
587 const std::stringstream& ss,
const char* file,
int line,
const char*
function)
592 if (g_printing_thread_id == boost::this_thread::get_id())
594 fprintf(stderr,
"Warning: recursive print statement has occurred. Throwing out recursive print.\n");
598 boost::mutex::scoped_lock lock(g_print_mutex);
600 g_printing_thread_id = boost::this_thread::get_id();
603 std::string str = ss.str();
611 params.
level = level;
612 params.
logger = logger_handle;
615 level = params.
level;
627 g_last_error_message = str;
633 catch (std::exception& e)
635 fprintf(stderr,
"Caught exception while logging: [%s]\n", e.what());
639 g_printing_thread_id = boost::thread::id();
647 boost::mutex::scoped_lock lock(g_locations_mutex);
649 g_log_locations.push_back(loc);
659 boost::mutex::scoped_lock lock(g_locations_mutex);
669 g_log_locations.push_back(loc);
678 boost::mutex::scoped_lock lock(g_locations_mutex);
684 boost::mutex::scoped_lock lock(g_locations_mutex);
690 boost::mutex::scoped_lock lock(g_locations_mutex);
692 V_LogLocation::iterator it = g_log_locations.begin();
693 V_LogLocation::iterator end = g_log_locations.end();
694 for ( ; it != end; ++it )
719 g_shutting_down =
true;
V_LogLocation g_log_locations
ROSCONSOLE_DECL void registerLogLocation(LogLocation *loc)
Registers a logging location with the system.
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...
void print(void *handle,::ros::console::Level level, const char *str, const char *file, const char *function, int line)
void(* function_print)(void *,::ros::console::Level, const char *, const char *, const char *, int)
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 ...
virtual std::string getString(void *,::ros::console::Level, const char *, const char *, const char *, int)
const char * g_format_string
Parameter structure passed to FilterBase::isEnabled(...);. Includes both input and output parameters...
virtual std::string getString(void *,::ros::console::Level, const char *, const char *, const char *, int)
::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...
virtual std::string getString(void *,::ros::console::Level, const char *, const char *, const char *, int line)
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, const char *, const char *file, const char *, int)
ROSCONSOLE_DECL void setFixedFilterToken(const std::string &key, const std::string &val)
std::string getName(void *handle)
virtual std::string getString(void *,::ros::console::Level, const char *, const char *, const char *, int)
std::vector< LogLocation * > V_LogLocation
const char * message
[input] The formatted message that will be output
virtual std::string getString(void *,::ros::console::Level level, const char *str, const char *file, const char *function, int line)
#define ROSCONSOLE_AUTOINIT
Initializes the rosconsole library. Usually unnecessary to call directly.
ROSCONSOLE_DECL bool g_initialized
Only exported because the macros need it. Do not use directly.
ROSCONSOLE_DECL std::string formatToString(const char *fmt,...)
void(* function_notifyLoggerLevelsChanged)()
virtual std::string getString(void *,::ros::console::Level, const char *, const char *, const char *, int)
ROSCONSOLE_DECL void checkLogLocationEnabled(LogLocation *loc)
Internal.
std::string out_message
[output] If set, writes this message instead of the original
virtual std::string getString(void *,::ros::console::Level, const char *str, const char *, const char *, int)
void register_appender(LogAppender *appender)
boost::shared_ptr< Token > TokenPtr
Level level
[input/output] Severity level. If changed, uses the new level
bool get_loggers(std::map< std::string, levels::Level > &loggers)
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
bool set_logger_level(const std::string &name, levels::Level level)
const char * function
[input] Function the message came from
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 *function, int)
#define INITIAL_BUFFER_SIZE
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
void _print(void *logger_handle,::ros::console::Level level, const char *str, const char *file, const char *function, int line)
void checkLogLocationEnabledNoLock(LogLocation *loc)
boost::mutex g_init_mutex
bool isEnabledFor(void *handle,::ros::console::Level level)
int line
[input] Line the message came from
static boost::shared_array< char > g_print_buffer(new char[INITIAL_BUFFER_SIZE])
void * getHandle(const std::string &name)
virtual std::string getString(void *logger_handle,::ros::console::Level level, const char *str, const char *file, const char *function, int line)
boost::mutex g_locations_mutex
ROSCONSOLE_DECL std::string g_last_error_message
Only exported because the TopicManager need it. Do not use directly.
#define ROS_ASSERT(cond)
Asserts that the provided condition evaluates to true.
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.
virtual std::string getString(void *,::ros::console::Level, const char *, const char *, const char *, int)
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