YARP
Yet Another Robot Platform
Log.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include <yarp/os/Log.h>
7
9#include <yarp/conf/system.h>
10
12#include <yarp/os/LogStream.h>
13#include <yarp/os/NetType.h>
14#include <yarp/os/Network.h>
15#include <yarp/os/SystemClock.h>
16#include <yarp/os/SystemInfo.h>
17#include <yarp/os/Time.h>
18
22
23#include <algorithm>
24#include <atomic>
25#include <cstdarg>
26#include <cstdio>
27#include <cstdlib>
28#include <cstring>
29#include <fstream>
30#include <iostream>
31#include <iomanip>
32#include <mutex>
33#include <sstream>
34
35#ifdef YARP_HAS_ACE
36# include <ace/Stack_Trace.h>
37// In one the ACE headers there is a definition of "main" for WIN32
38# ifdef main
39# undef main
40# endif
41#elif defined(YARP_HAS_EXECINFO_H)
42# include <execinfo.h>
43#endif
44
45#ifdef YARP_HAS_WIN_VT_SUPPORT
46#include <windows.h>
47#endif
48
49
51{
52public:
53 LogPrivate(const char* file,
54 const unsigned int line,
55 const char* func,
56 const char* id,
57 const double externaltime,
59 const LogComponent& comp);
60
62 const char *msg,
63 va_list args) const;
64
66 const char* msg,
67 const char* file,
68 const unsigned int line,
69 const char* func,
70 double systemtime,
71 double networktime,
72 double externaltime,
73 const char* comp_name,
74 const char* id);
75
77 const char* msg,
78 const char* file,
79 const unsigned int line,
80 const char* func,
81 double systemtime,
82 double networktime,
83 double externaltime,
84 const char* comp_name,
85 const char* id);
86
87 // Calls the right print and forward callbacks
88 static void do_log(yarp::os::Log::LogType type,
89 const char* msg,
90 const char* file,
91 const unsigned int line,
92 const char* func,
93 double systemtime,
94 double networktime,
95 double externaltime,
96 const LogComponent& comp_name,
97 const std::string_view id);
98
99 // This is a LogCallback that calls the print callback that is currently
100 // set, even if this is changed later
102 const char* msg,
103 const char* file,
104 const unsigned int line,
105 const char* func,
106 double systemtime,
107 double networktime,
108 double externaltime,
109 const char* comp_name,
110 const char* id)
111 {
112 if (auto cb = current_print_callback.load()) {
113 cb(type, msg, file, line, func, systemtime, networktime, externaltime, comp_name, id);
114 }
115 }
116
117 // This is a LogCallback that calls the forward callback that is currently
118 // set, even if this is changed later
120 const char* msg,
121 const char* file,
122 const unsigned int line,
123 const char* func,
124 double systemtime,
125 double networktime,
126 double externaltime,
127 const char* comp_name,
128 const char* id)
129 {
130 if (auto cb = current_forward_callback.load()) {
131 cb(type, msg, file, line, func, systemtime, networktime, externaltime, comp_name, id);
132 }
133 }
134
136
137#ifdef YARP_HAS_WIN_VT_SUPPORT
138 bool enable_vt_colors();
139#endif
140
141 const char* file;
142 const unsigned int line;
143 const char* func;
149 const char* id;
150
151 static std::atomic<bool> yarprun_format;
152 static std::atomic<bool> colored_output;
153 static std::atomic<bool> verbose_output;
154 static std::atomic<bool> compact_output;
155 static std::atomic<bool> debug_output;
156 static std::atomic<bool> trace_output;
157 static std::atomic<bool> forward_output;
158 static std::atomic<bool> forward_codeinfo;
159 static std::atomic<bool> forward_hostname;
160 static std::atomic<bool> forward_processinfo;
161 static std::atomic<bool> forward_backtrace;
162 static std::atomic<bool> debug_log;
163#ifdef YARP_HAS_WIN_VT_SUPPORT
164 static std::atomic<bool> vt_colors_enabled;
165#endif
166
167 static std::atomic<yarp::os::Log::LogType> current_minimum_print_level;
168 static std::atomic<yarp::os::Log::LogType> current_minimum_forward_level;
169
170 static std::atomic<Log::LogCallback> current_print_callback;
171 static std::atomic<Log::LogCallback> current_forward_callback;
172
174};
175
176// BEGIN Utilities
177
178#define BOLD_RED (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;31m" : "")
179#define BOLD_GREEN (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;32m" : "")
180#define BOLD_YELLOW (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;33m" : "")
181#define BOLD_BLUE (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;34m" : "")
182#define BOLD_MAGENTA (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;35m" : "")
183#define BOLD_CYAN (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;36m" : "")
184#define BOLD_WHITE (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;37m" : "")
185#define RED (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[31m" : "")
186#define GREEN (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[32m" : "")
187#define YELLOW (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[33m" : "")
188#define BLUE (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[34m" : "")
189#define MAGENTA (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[35m" : "")
190#define CYAN (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[36m" : "")
191#define WHITE (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[37m" : "")
192#define RED_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[41m" : "")
193#define GREEN_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[42m" : "")
194#define YELLOW_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[43m" : "")
195#define BLUE_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[44m" : "")
196#define MAGENTA_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[45m" : "")
197#define CYAN_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[46m" : "")
198#define WHITE_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[47m" : "")
199#define CLEAR (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[00m" : "")
200
201namespace {
202
203inline const char* logTypeToString(yarp::os::Log::LogType t)
204{
205 switch (t) {
207 return "TRACE";
209 return "DEBUG";
211 return "INFO";
213 return "WARNING";
215 return "ERROR";
217 return "FATAL";
218 default:
219 return "";
220 }
221}
222
223inline const char* logTypeToColor(yarp::os::Log::LogType t)
224{
225 switch (t) {
227 return BOLD_WHITE;
229 return BOLD_GREEN;
231 return BOLD_BLUE;
233 return BOLD_YELLOW;
235 return BOLD_RED;
237 return BOLD_WHITE;
239 return CYAN;
240 default:
241 return "";
242 }
243}
244
245inline const char* logTypeToBgColor(yarp::os::Log::LogType t)
246{
247 switch (t) {
249 return RED_BG;
255 default:
256 return "";
257 }
258}
259
260inline const char* compNameToColor(const char* comp_name)
261{
262 if (!comp_name || comp_name[0] == '\0' || !yarp::os::impl::LogPrivate::colored_output.load()) {
263 return "";
264 }
265
266 // Hashing the component for every log line is probably not optimal, but in
267 // using a hash table will have the hash + a search, and since the
268 // LogCallback has only the name of the component, we cannot store the color
269 // in the LogComponent without breaking the API, therefore this is the less
270 // invasive option.
271 // Anyway, this is enabled only when YARP_COLORED_OUTPUT is set, therefore
272 // it can be easily disabled if this slows down the execution.
273 static std::hash<std::string_view> hsh;
274 std::size_t comp_hash = hsh(comp_name) % 6;
275 switch (comp_hash) {
276 // BOLD_RED is not used, since this is easily confused with an error
277 case 0:
278 return BOLD_GREEN;
279 case 1:
280 return BOLD_YELLOW;
281 case 2:
282 return BOLD_BLUE;
283 case 3:
284 return BOLD_MAGENTA;
285 case 4:
286 return BOLD_CYAN;
287 case 5:
288 return BOLD_WHITE;
289 default:
290 return "";
291 }
292}
293
294inline const char* idToColor(const char* id)
295{
296 if (!id || id[0] == '\0' || !yarp::os::impl::LogPrivate::colored_output.load()) {
297 return "";
298 }
299
300 // Hashing the component for every log line is probably not optimal, but in
301 // using a hash table will have the hash + a search, and since the
302 // LogCallback has only the name of the component, we cannot store the color
303 // in the LogComponent without breaking the API, therefore this is the less
304 // invasive option.
305 // Anyway, this is enabled only when YARP_COLORED_OUTPUT is set, therefore
306 // it can be easily disabled if this slows down the execution.
307 static std::hash<std::string_view> hsh;
308 std::size_t id_hash = hsh(id) % 6;
309 switch (id_hash) {
310 case 0:
311 return RED;
312 case 1:
313 return GREEN;
314 case 2:
315 return YELLOW;
316 case 3:
317 return BLUE;
318 case 4:
319 return MAGENTA;
320 case 5:
321 return CYAN;
322 default:
323 return "";
324 }
325}
326
327std::string backtrace()
328{
329#ifdef YARP_HAS_ACE
330 ACE_Stack_Trace st(-1);
331 // TODO demangle symbols using <cxxabi.h> and abi::__cxa_demangle
332 // when available.
333 return {st.c_str()};
334#elif defined(YARP_HAS_EXECINFO_H)
335 const size_t max_depth = 100;
336 size_t stack_depth;
337 void* stack_addrs[max_depth];
338 char** stack_strings;
339 stack_depth = ::backtrace(stack_addrs, max_depth);
340 stack_strings = backtrace_symbols(stack_addrs, stack_depth);
341 std::ostringstream ost;
342 for (size_t i = 1; i < stack_depth; i++) {
343 ost << stack_strings[i] << '\n';
344 }
345 free(stack_strings); // malloc()ed by backtrace_symbols
346 return ost.str();
347#else
348 // Not implemented on this platform
349 return {};
350#endif
351}
352
353inline void forwardable_output(std::ostream* ost,
355 const char* msg,
356 const char* file,
357 const unsigned int line,
358 const char* func,
359 double systemtime,
360 double networktime,
361 double externaltime,
362 const char* comp_name,
363 const char* id)
364{
365 const char *level = logTypeToString(t);
366
367 // This generates the same string a Property containing the following keys:
368 // * level
369 // * systemtime
370 // * networktime (if not using system time)
371 // * externaltime (if defined)
372 // * filename (if YARP_FORWARD_CODEINFO_ENABLE is enabled)
373 // * line (if YARP_FORWARD_CODEINFO_ENABLE is enabled)
374 // * function (if YARP_FORWARD_CODEINFO_ENABLE is enabled)
375 // * hostname (if YARP_FORWARD_HOSTNAME_ENABLE is enabled)
376 // * cmd (if YARP_FORWARD_PROCESSINFO_ENABLE is enabled)
377 // * args (if YARP_FORWARD_PROCESSINFO_ENABLE is enabled)
378 // * pid (if YARP_FORWARD_PROCESSINFO_ENABLE is enabled)
379 // * thread_id (if YARP_FORWARD_PROCESSINFO_ENABLE is enabled)
380 // * component (if defined)
381 // * id (if defined)
382 // * message (if any)
383 // * backtrace (for FATAL or if requested using YARP_FORWARD_BACKTRACE_ENABLE)
384
385 *ost << "(level " << yarp::os::impl::StoreString::quotedString(level) << ")";
386 *ost << " (systemtime " << yarp::conf::numeric::to_string(systemtime) << ")";
388 *ost << " (networktime " << yarp::conf::numeric::to_string(networktime) << ")";
389 }
390 if (externaltime != 0.0) {
391 *ost << " (externaltime " << yarp::conf::numeric::to_string(externaltime) << ")";
392 }
394 *ost << " (filename " << yarp::os::impl::StoreString::quotedString(file) << ")";
395 *ost << " (line " << line << ")";
396 *ost << " (function " << yarp::os::impl::StoreString::quotedString(func) << ")";
397 }
399 static std::string hostname(yarp::os::gethostname());
400 *ost << " (hostname " << yarp::os::impl::StoreString::quotedString(hostname) << ")";
401 }
404 static std::string cmd(processInfo.name.substr(processInfo.name.find_last_of("\\/") + 1));
405 thread_local long thread_id(yarp::os::impl::ThreadImpl::getKeyOfCaller());
406 *ost << " (pid " << processInfo.pid << ")";
407 *ost << " (cmd " << yarp::os::impl::StoreString::quotedString(cmd) << ")";
408 *ost << " (args " << yarp::os::impl::StoreString::quotedString(processInfo.arguments) << ")";
409 *ost << " (thread_id 0x" << std::setfill('0') << std::setw(8) << yarp::conf::numeric::to_hex_string(thread_id) << ")";
410 }
411 if (comp_name) {
412 *ost << " (component " << yarp::os::impl::StoreString::quotedString(comp_name) << ")";
413 }
414 if (id && id[0] != '\0') {
415 *ost << " (id " << yarp::os::impl::StoreString::quotedString(id) << ")";
416 }
417 if (msg[0]) {
418 *ost << " (message " << yarp::os::impl::StoreString::quotedString(msg) << ")";
419 }
421 *ost << " (backtrace " << yarp::os::impl::StoreString::quotedString(backtrace()) << ")";
422 }
423}
424
425inline void printable_output(std::ostream* ost,
427 const char* msg,
428 const char* file,
429 const unsigned int line,
430 const char* func,
431 double systemtime,
432 double networktime,
433 double externaltime,
434 const char* comp_name,
435 const char* id)
436{
437 YARP_UNUSED(file);
438 YARP_UNUSED(line);
439 YARP_UNUSED(systemtime);
440 YARP_UNUSED(networktime);
441 YARP_UNUSED(externaltime);
442
443#if !defined (_MSC_VER)
444 static constexpr const char* level_char = u8"\u25CF";
445#else
446 static constexpr const char* level_char = "*";
447#endif
448
449 const char* level_string = logTypeToString(t);
450 const char* level_color = logTypeToColor(t);
451 const char* level_bgcolor = logTypeToBgColor(t);
452 static const char *reserved_color = logTypeToColor(yarp::os::Log::LogTypeReserved);
453 const char* comp_color = compNameToColor(comp_name);
454 const char* id_color = idToColor(id);
455
456 // Print Level
458 *ost << level_color << level_bgcolor << level_char << CLEAR << " ";
459 } else {
460 *ost << "[" << level_color << level_bgcolor << level_string << CLEAR << "] ";
461 }
462
463 // Print function information (trace only)
465 *ost << level_color << func << CLEAR << ((msg[0] || comp_name) ? ": " : "");
466 }
467
468 // Print component and id
469 if (comp_name) {
470 *ost << "|" << comp_color << comp_name << CLEAR << "|";
471 }
472 if (id && id[0] != '\0') {
473 if (!comp_name) {
474 *ost << "|";
475 }
476 *ost << id_color << id << CLEAR << "| ";
477 } else if (comp_name) {
478 *ost << " ";
479 }
480
481 // Finally print the message
483 *ost << reserved_color << '^' << CLEAR;
484 }
485 *ost << msg;
487 *ost << reserved_color << '$' << CLEAR;
488 }
489}
490
491inline void printable_output_verbose(std::ostream* ost,
493 const char* msg,
494 const char* file,
495 const unsigned int line,
496 const char* func,
497 double systemtime,
498 double networktime,
499 double externaltime,
500 const char* comp_name,
501 const char* id)
502{
503 YARP_UNUSED(systemtime);
504
505 const char* level_string = logTypeToString(t);
506 const char *level_color = logTypeToColor(t);
507 const char *level_bgcolor = logTypeToBgColor(t);
508 static const char *reserved_color = logTypeToColor(yarp::os::Log::LogTypeReserved);
509 const char* comp_color = compNameToColor(comp_name);
510 const char* id_color = idToColor(comp_name);
511
512 // Print external time
513 if (externaltime != 0.0) {
514 *ost << "[" << std::fixed << externaltime << "] ";
515 }
516 else {
517 // Print time
518 *ost << "[" << std::fixed << networktime << "] ";
519 }
520
521 // Print level
522 *ost << "[" << level_color << level_bgcolor << level_string << CLEAR << "] ";
523
524 // Print file, line and function
525 *ost << file << ":" << line << " " << level_color << level_bgcolor << func << CLEAR << " ";
526
527 // Print thread id
528 *ost << "(0x" << std::setfill('0') << std::setw(8) << yarp::conf::numeric::to_hex_string(yarp::os::impl::ThreadImpl::getKeyOfCaller()) << ") ";
529
530 // Print component and id
531 if (comp_name) {
532 *ost << "|" << comp_color << comp_name << CLEAR << "|";
533 }
534 if (id && id[0] != '\0') {
535 if (!comp_name) {
536 *ost << "|";
537 }
538 *ost << id_color << id << CLEAR << "| ";
539 } else if (comp_name) {
540 *ost << " ";
541 }
542
543 // Finally print the message
545 *ost << reserved_color << '^' << CLEAR;
546 }
547 *ost << msg;
549 *ost << reserved_color << '$' << CLEAR;
550 }
551}
552
553} // namespace
554
555// END Utilities
556
557// BEGIN LogPrivate static variables initialization
558
559// BEGIN Environment variables
560std::atomic<bool> yarp::os::impl::LogPrivate::yarprun_format(yarp::conf::environment::get_bool("YARP_IS_YARPRUN", false) &&
561 yarp::conf::environment::get_bool("YARPRUN_IS_FORWARDING_LOG", false));
562
563#if defined(_WIN32) && !defined(YARP_HAS_WIN_VT_SUPPORT)
564std::atomic<bool> yarp::os::impl::LogPrivate::colored_output(false);
565#else
566std::atomic<bool> yarp::os::impl::LogPrivate::colored_output(yarp::conf::environment::get_bool("YARP_COLORED_OUTPUT", false) &&
568#endif
569std::atomic<bool> yarp::os::impl::LogPrivate::verbose_output(yarp::conf::environment::get_bool("YARP_VERBOSE_OUTPUT", false) &&
571std::atomic<bool> yarp::os::impl::LogPrivate::compact_output(yarp::conf::environment::get_bool("YARP_COMPACT_OUTPUT", false) &&
574std::atomic<bool> yarp::os::impl::LogPrivate::forward_output(yarp::conf::environment::get_bool("YARP_FORWARD_LOG_ENABLE", false) &&
576
577// The following 4 environment variables are to be considered experimental
578// until we have a reason to believe that this extra traffic does not impact
579// on the performances (and that all these info are actually useful).
580std::atomic<bool> yarp::os::impl::LogPrivate::forward_codeinfo(yarp::conf::environment::get_bool("YARP_FORWARD_CODEINFO_ENABLE", false));
581std::atomic<bool> yarp::os::impl::LogPrivate::forward_hostname(yarp::conf::environment::get_bool("YARP_FORWARD_HOSTNAME_ENABLE", false));
582std::atomic<bool> yarp::os::impl::LogPrivate::forward_processinfo(yarp::conf::environment::get_bool("YARP_FORWARD_PROCESSINFO_ENABLE", false));
583std::atomic<bool> yarp::os::impl::LogPrivate::forward_backtrace(yarp::conf::environment::get_bool("YARP_FORWARD_BACKTRACE_ENABLE", false));
584
585std::atomic<bool> yarp::os::impl::LogPrivate::debug_output(yarp::conf::environment::get_bool("YARP_DEBUG_ENABLE", true));
586std::atomic<bool> yarp::os::impl::LogPrivate::trace_output(yarp::conf::environment::get_bool("YARP_TRACE_ENABLE", false) &&
588
589std::atomic<bool> yarp::os::impl::LogPrivate::debug_log(yarp::conf::environment::get_bool("YARP_DEBUG_LOG_ENABLE", false));
590// END Environment variables
591
592#ifdef YARP_HAS_WIN_VT_SUPPORT
593std::atomic<bool> yarp::os::impl::LogPrivate::vt_colors_enabled = false;
594#endif
595
596
597std::atomic<yarp::os::Log::LogType> yarp::os::impl::LogPrivate::current_minimum_print_level(
601
602std::atomic<yarp::os::Log::LogType> yarp::os::impl::LogPrivate::current_minimum_forward_level(
605
607
608std::atomic<yarp::os::Log::LogCallback> yarp::os::impl::LogPrivate::current_forward_callback(
610 : nullptr);
611
612// Log internal component never forwards the output and, if enabled, prints
613// all the output using the default print callback
615 "yarp.os.Log",
620 : nullptr,
621 nullptr);
622
623
624// END LogPrivate static variables initialization
625
626// BEGIN LogPrivate methods
627
629 unsigned int line,
630 const char* func,
631 const char* id,
632 const double externaltime,
633 const yarp::os::Log::Predicate pred,
634 const LogComponent& comp) :
635 file(file),
636 line(line),
637 func(func),
638 systemtime(yarp::os::SystemClock::nowSystem()),
639 networktime(!yarp::os::NetworkBase::isNetworkInitialized() ? 0.0 : (yarp::os::Time::isSystemClock() ? systemtime : yarp::os::Time::now())),
640 externaltime(externaltime),
641 pred(pred),
642 comp(comp),
643 id(id)
644{
645#ifdef YARP_HAS_WIN_VT_SUPPORT
646 if (colored_output.load() && !yarp::os::impl::LogPrivate::vt_colors_enabled.load()) {
647 colored_output = enable_vt_colors();
648 }
649#endif
650}
651
653 const char* msg,
654 const char* file,
655 const unsigned int line,
656 const char* func,
657 double systemtime,
658 double networktime,
659 double externaltime,
660 const char* comp_name,
661 const char* id)
662{
663 std::ostream *ost;
667 ost = &std::cout;
668 } else {
669 ost = &std::cerr;
670 }
671
672 static std::mutex log_mutex;
673 std::lock_guard<std::mutex> lock(log_mutex);
674
675 if (yarprun_format.load()) {
676 // Same output as forward_callback
677 forwardable_output(ost, t, msg, file, line, func, systemtime, networktime, externaltime, comp_name, id);
678 } else if (verbose_output.load()) {
679 printable_output_verbose(ost, t, msg, file, line, func, systemtime, networktime, externaltime, comp_name, id);
680 } else {
681 printable_output(ost, t, msg, file, line, func, systemtime, networktime, externaltime, comp_name, id);
682 }
683 *ost << std::endl;
684}
685
687 const char* msg,
688 const char* file,
689 const unsigned int line,
690 const char* func,
691 double systemtime,
692 double networktime,
693 double externaltime,
694 const char* comp_name,
695 const char* id)
696{
698 // Network is not initialized. Don't forward any log.
699 // And avoid creating the LogForwarder!
700 return;
701 }
702 std::stringstream stringstream_buffer;
703 forwardable_output(&stringstream_buffer, t, msg, file, line, func, systemtime, networktime, externaltime, comp_name, id);
704 LogForwarder::getInstance().forward(stringstream_buffer.str());
705}
706
708 const char* msg,
709 va_list args) const
710{
711 constexpr size_t YARP_MAX_STATIC_LOG_MSG_SIZE = 1024;
712
713 if (msg != nullptr) {
714 if (!pred || pred()) {
715 char buf[YARP_MAX_STATIC_LOG_MSG_SIZE];
716 char* dyn_buf = nullptr;
717
718 char* out = buf;
719 size_t buf_size = YARP_MAX_STATIC_LOG_MSG_SIZE;
720
721 // Save va_list status in case we need to repeat the operation with
722 // the dynamically allocated buffer (vsnprintf leaves it in an
723 // undefined status).
724 va_list args_bak;
725 va_copy(args_bak, args);
726
727 auto log_line_size = static_cast<size_t>(std::vsnprintf(buf, YARP_MAX_STATIC_LOG_MSG_SIZE, msg, args));
728
729 if (log_line_size > YARP_MAX_STATIC_LOG_MSG_SIZE) {
730 // The static buffer is not big enough for the log line.
731 // Using a dynamic buffer instead.
732 // Round up size to the first power of 2.
733 size_t dyn_buf_size = [](size_t x) {
734 --x;
735 x |= x >> 1;
736 x |= x >> 2;
737 x |= x >> 4;
738 x |= x >> 8;
739 x |= x >> 16;
740 return x + 1;
741 }(log_line_size);
742
743 dyn_buf = new char[dyn_buf_size];
744 std::vsnprintf(dyn_buf, dyn_buf_size, msg, args_bak);
745 va_end(args_bak);
746
747 out = dyn_buf;
748 buf_size = dyn_buf_size;
749 }
750
751 auto p = std::min(log_line_size - 1, buf_size);
752 if (log_line_size > 0 && p < buf_size && out[p] == '\n' && msg[strlen(msg) - 1] == '\n') {
753 yarp::os::Log(file, line, func, nullptr, log_internal_component).warning("Removing extra '\\n' (c-style)");
754 out[p] = 0;
755 }
756
757 do_log(type, out, file, line, func, systemtime, networktime, externaltime, comp, id);
758
759 if (dyn_buf) {
760 yarp::os::Log(file, line, func, nullptr, log_internal_component).warning("Previous message was longer than the static buffer size, dynamic allocation was used");
761 delete[] dyn_buf;
762 }
763 }
764 } else {
765 yarp::os::Log(file, line, func, nullptr, log_internal_component).warning("Unexpected nullptr received");
766 }
767}
768
770 const char* msg,
771 const char* file,
772 const unsigned int line,
773 const char* func,
774 double systemtime,
775 double networktime,
776 double externaltime,
777 const LogComponent& comp,
778 const std::string_view id)
779{
780 auto* print_cb = (yarprun_format && comp != log_internal_component) ? yarp::os::impl::LogPrivate::print_callback : comp.printCallback(type);
781 if (print_cb) {
782 print_cb(type, msg, file, line, func, systemtime, networktime, externaltime, comp.name(), id.data());
783 } else {
784 if (comp != log_internal_component) {
785 if (comp.name()) {
786 yarp::os::Log(file, line, func, nullptr, log_internal_component).debug("Not printing [%s][%s]", comp.name(), msg);
787 } else {
788 yarp::os::Log(file, line, func, nullptr, log_internal_component).debug("Not printing [%s]", msg);
789 }
790 }
791 }
792
793 auto* forward_cb = comp.forwardCallback(type);
794 if(forward_cb) {
795 forward_cb(type, msg, file, line, func, systemtime, networktime, externaltime, comp.name(), id.data());
796 } else {
797 if (comp != log_internal_component) {
798 if (comp.name()) {
799 yarp::os::Log(file, line, func, nullptr, log_internal_component).debug("Not forwarding [%s][%s]", comp.name(), msg);
800 } else {
801 yarp::os::Log(file, line, func, nullptr, log_internal_component).debug("Not forwarding [%s]", msg);
802 }
803 }
804 }
805}
806
807#ifdef YARP_HAS_WIN_VT_SUPPORT
808bool yarp::os::impl::LogPrivate::enable_vt_colors()
809{
810 DWORD handleMode = 0;
811 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
812 bool success = false;
813
814 if (hStdout != INVALID_HANDLE_VALUE && GetConsoleMode(hStdout, &handleMode)) {
815 handleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
816 success = SetConsoleMode(hStdout, handleMode);
817 }
818
819 yarp::os::impl::LogPrivate::vt_colors_enabled = true;
820 return success;
821}
822#endif
823
824// END LogPrivate methods
825
826
827// BEGIN Minimum Print Level
829{
831}
832
834{
836}
837
839{
841}
842// END Minimum Print Level
843
844
845// BEGIN Minimum Forward Level
847{
850 }
851}
852
854{
856}
857
859{
861}
862
863// END Minimum Forward Level
864
865
866// BEGIN Print Callback
867
868#ifndef YARP_NO_DEPRECATED // Since YARP 3.4
870{
872}
873#endif
874
876{
878}
879
881{
883}
884
886{
888}
889
890// END Print Callback
891
892
893// BEGIN Forward Callback
894
896{
899 }
900}
901
903{
905}
906
908{
910}
911
912// END Forward Callback
913
914
915// BEGIN Log Components
916const yarp::os::LogComponent& yarp::os::Log::defaultLogComponent()
917{
918 static const yarp::os::LogComponent component(nullptr,
919 minimumPrintLevel(),
920 minimumForwardLevel(),
921 printCallback(),
922 forwardCallback());
923 return component;
924}
925
926const yarp::os::LogComponent& yarp::os::Log::logInternalComponent()
927{
929}
930// END Log Components
931
932
933yarp::os::Log::Log(const char* file,
934 unsigned int line,
935 const char* func,
936 const Predicate pred,
937 const LogComponent& comp) :
938 mPriv(new yarp::os::impl::LogPrivate(file, line, func, "", 0.0, pred, comp))
939{
940}
941
942// method for Log with id
943yarp::os::Log::Log(const char* file,
944 unsigned int line,
945 const char* func,
946 std::string_view id,
947 const Predicate pred,
948 const LogComponent& comp) :
949 mPriv(new yarp::os::impl::LogPrivate(file, line, func, id.data(), 0.0, pred, comp))
950{
951}
952
953// method for Log with externaltime
954yarp::os::Log::Log(const char* file,
955 unsigned int line,
956 const char* func,
957 const double externaltime,
958 const Predicate pred,
959 const LogComponent& comp) :
960 mPriv(new yarp::os::impl::LogPrivate(file, line, func, "", externaltime, pred, comp))
961{
962}
963
964// method for Log with id and externaltime
965
966yarp::os::Log::Log(const char* file,
967 unsigned int line,
968 const char* func,
969 std::string_view id,
970 const double externaltime,
971 const Predicate pred,
972 const LogComponent& comp) :
973 mPriv(new yarp::os::impl::LogPrivate(file, line, func, id.data(), externaltime, pred, comp))
974{
975}
976
978 mPriv(new yarp::os::impl::LogPrivate(nullptr, 0, nullptr, nullptr, 0.0, nullptr, nullptr))
979{
980}
981
983{
984 delete mPriv;
985}
986
987void yarp::os::Log::do_log(yarp::os::Log::LogType type,
988 const char* msg,
989 const char* file,
990 const unsigned int line,
991 const char* func,
992 double systemtime,
993 double networktime,
994 double externaltime,
995 const LogComponent& comp,
996 const std::string_view id)
997{
998 yarp::os::impl::LogPrivate::do_log(type, msg, file, line, func, systemtime, networktime, externaltime, comp, id);
999}
1000
1001
1002void yarp::os::Log::trace(const char* msg, ...) const
1003{
1004 va_list args;
1005 va_start(args, msg);
1006 mPriv->log(yarp::os::Log::TraceType, msg, args);
1007 va_end(args);
1008}
1009
1011{
1013 mPriv->file,
1014 mPriv->line,
1015 mPriv->func,
1016 mPriv->id,
1017 mPriv->externaltime,
1018 mPriv->pred,
1019 mPriv->comp);
1020}
1021
1022
1023void yarp::os::Log::debug(const char* msg, ...) const
1024{
1025 va_list args;
1026 va_start(args, msg);
1027 mPriv->log(yarp::os::Log::DebugType, msg, args);
1028 va_end(args);
1029}
1030
1032{
1034 mPriv->file,
1035 mPriv->line,
1036 mPriv->func,
1037 mPriv->id,
1038 mPriv->externaltime,
1039 mPriv->pred,
1040 mPriv->comp);
1041}
1042
1043void yarp::os::Log::info(const char* msg, ...) const
1044{
1045 va_list args;
1046 va_start(args, msg);
1047 mPriv->log(yarp::os::Log::InfoType, msg, args);
1048 va_end(args);
1049}
1050
1052{
1054 mPriv->file,
1055 mPriv->line,
1056 mPriv->func,
1057 mPriv->id,
1058 mPriv->externaltime,
1059 mPriv->pred,
1060 mPriv->comp);
1061}
1062
1063
1064void yarp::os::Log::warning(const char* msg, ...) const
1065{
1066 va_list args;
1067 va_start(args, msg);
1068 mPriv->log(yarp::os::Log::WarningType, msg, args);
1069 va_end(args);
1070}
1071
1073{
1075 mPriv->file,
1076 mPriv->line,
1077 mPriv->func,
1078 mPriv->id,
1079 mPriv->externaltime,
1080 mPriv->pred,
1081 mPriv->comp);
1082}
1083
1084
1085void yarp::os::Log::error(const char* msg, ...) const
1086{
1087 va_list args;
1088 va_start(args, msg);
1089 mPriv->log(yarp::os::Log::ErrorType, msg, args);
1090 va_end(args);
1091}
1092
1094{
1096 mPriv->file,
1097 mPriv->line,
1098 mPriv->func,
1099 mPriv->id,
1100 mPriv->externaltime,
1101 mPriv->pred,
1102 mPriv->comp);
1103}
1104
1105void yarp::os::Log::fatal(const char* msg, ...) const
1106{
1107 va_list args;
1108 va_start(args, msg);
1109 mPriv->log(yarp::os::Log::FatalType, msg, args);
1110 va_end(args);
1111 yarp_print_trace(stderr, mPriv->file, mPriv->line);
1112 std::exit(-1);
1113}
1114
1116{
1118 mPriv->file,
1119 mPriv->line,
1120 mPriv->func,
1121 mPriv->id,
1122 mPriv->externaltime,
1123 mPriv->pred,
1124 mPriv->comp);
1125}
1126
1127void yarp_print_trace(FILE* out, const char* file, unsigned int line)
1128{
1129 fprintf(out, "Trace requested at %s:%u by code called from:\n", file, line);
1130 fprintf(out, "%s", backtrace().c_str());
1131 fflush(out);
1132}
float t
#define BOLD_MAGENTA
Definition: Log.cpp:182
#define BOLD_BLUE
Definition: Log.cpp:181
#define BOLD_GREEN
Definition: Log.cpp:179
#define BOLD_YELLOW
Definition: Log.cpp:180
#define BOLD_RED
Definition: Log.cpp:178
#define CLEAR
Definition: Log.cpp:199
#define BOLD_CYAN
Definition: Log.cpp:183
#define MAGENTA
Definition: Log.cpp:189
#define BLUE
Definition: Log.cpp:188
#define RED
Definition: Log.cpp:185
#define BOLD_WHITE
Definition: Log.cpp:184
void yarp_print_trace(FILE *out, const char *file, unsigned int line)
Low level function for printing a stack trace, if implemented (ACE or gcc/Linux).
Definition: Log.cpp:1127
#define YELLOW
Definition: Log.cpp:187
#define GREEN
Definition: Log.cpp:186
#define CYAN
Definition: Log.cpp:190
#define RED_BG
Definition: Log.cpp:192
void * HANDLE
constexpr const char * name() const
Definition: LogComponent.h:38
LogCallback printCallback(yarp::os::Log::LogType t) const
LogCallback forwardCallback(yarp::os::Log::LogType t) const
static void setLogCallback(LogCallback)
Definition: Log.cpp:869
LogStream trace() const
Definition: Log.cpp:1010
static LogCallback printCallback()
Get current print callback.
Definition: Log.cpp:880
bool(*)() Predicate
Definition: Log.h:52
void warning(const char *msg,...) const
Definition: Log.cpp:1064
static LogType defaultMinimumPrintLevel()
Get default minimum print level.
Definition: Log.cpp:838
virtual ~Log()
Definition: Log.cpp:982
void debug(const char *msg,...) const
Definition: Log.cpp:1023
static LogType minimumPrintLevel()
Get current minimum print level.
Definition: Log.cpp:833
static LogCallback forwardCallback()
Get current forward callback (or nullptr if forwarding is not enabled)
Definition: Log.cpp:902
static LogType minimumForwardLevel()
Get current minimum forward level (or LogTypeReserved if forwarding is not enabled)
Definition: Log.cpp:853
LogStream error() const
Definition: Log.cpp:1093
LogStream warning() const
Definition: Log.cpp:1072
static void setPrintCallback(LogCallback)
Set current print callback.
Definition: Log.cpp:875
LogStream debug() const
Definition: Log.cpp:1031
@ ErrorType
Definition: Log.h:95
@ LogTypeReserved
Definition: Log.h:97
@ DebugType
Definition: Log.h:92
@ TraceType
Definition: Log.h:91
@ InfoType
Definition: Log.h:93
@ FatalType
Definition: Log.h:96
@ WarningType
Definition: Log.h:94
static LogType defaultMinimumForwardLevel()
Get default minimum forward level (or LogTypeReserved if forwarding is not enabled)
Definition: Log.cpp:858
static void setForwardCallback(LogCallback)
Set current forward callback (it does nothing if forwarding is not enabled)
Definition: Log.cpp:895
LogStream fatal() const
Definition: Log.cpp:1115
static void setMinimumForwardLevel(LogType level)
Set current minimum forward level (it does nothing if forwarding is not enabled)
Definition: Log.cpp:846
static LogCallback defaultPrintCallback()
Get default print callback.
Definition: Log.cpp:885
LogStream info() const
Definition: Log.cpp:1051
void(*)(yarp::os::Log::LogType type, const char *msg, const char *file, const unsigned int line, const char *func, double systemtime, double networktime, double externaltime, const char *comp_name, const char *id) LogCallback
Definition: Log.h:123
static LogCallback defaultForwardCallback()
Get default forward callback (or nullptr if forwarding is not enabled)
Definition: Log.cpp:907
static void setMinimumPrintLevel(LogType level)
Set current minimum print level.
Definition: Log.cpp:828
Utilities for manipulating the YARP network, excluding initialization and shutdown.
Definition: Network.h:38
static bool isNetworkInitialized()
Definition: Network.cpp:876
static ProcessInfo getProcessInfo(int pid=0)
gets the operating system process information given by its PID.
Definition: SystemInfo.cpp:805
void forward(const std::string &message)
static LogForwarder & getInstance()
static std::atomic< bool > forward_hostname
Definition: Log.cpp:159
static std::atomic< Log::LogCallback > current_forward_callback
Definition: Log.cpp:171
const unsigned int line
Definition: Log.cpp:142
static std::atomic< bool > debug_output
Definition: Log.cpp:155
void log(yarp::os::Log::LogType type, const char *msg, va_list args) const
Definition: Log.cpp:707
static std::atomic< bool > forward_codeinfo
Definition: Log.cpp:158
static void forward_callback(yarp::os::Log::LogType t, const char *msg, const char *file, const unsigned int line, const char *func, double systemtime, double networktime, double externaltime, const char *comp_name, const char *id)
Definition: Log.cpp:686
static void print_callback(yarp::os::Log::LogType t, const char *msg, const char *file, const unsigned int line, const char *func, double systemtime, double networktime, double externaltime, const char *comp_name, const char *id)
Definition: Log.cpp:652
static std::atomic< yarp::os::Log::LogType > current_minimum_print_level
Definition: Log.cpp:167
static std::atomic< bool > colored_output
Definition: Log.cpp:152
const char * file
Definition: Log.cpp:141
static std::atomic< Log::LogCallback > current_print_callback
Definition: Log.cpp:170
const yarp::os::Log::Predicate pred
Definition: Log.cpp:147
static std::atomic< bool > forward_processinfo
Definition: Log.cpp:160
static std::atomic< yarp::os::Log::LogType > current_minimum_forward_level
Definition: Log.cpp:168
static std::atomic< bool > trace_output
Definition: Log.cpp:156
static std::atomic< bool > verbose_output
Definition: Log.cpp:153
static std::atomic< bool > debug_log
Definition: Log.cpp:162
static const LogComponent & logInternalComponent()
LogPrivate(const char *file, const unsigned int line, const char *func, const char *id, const double externaltime, const yarp::os::Log::Predicate pred, const LogComponent &comp)
Definition: Log.cpp:628
static const yarp::os::LogComponent log_internal_component
Definition: Log.cpp:173
static std::atomic< bool > yarprun_format
Definition: Log.cpp:151
static void call_current_print_callback(yarp::os::Log::LogType type, const char *msg, const char *file, const unsigned int line, const char *func, double systemtime, double networktime, double externaltime, const char *comp_name, const char *id)
Definition: Log.cpp:101
static std::atomic< bool > forward_output
Definition: Log.cpp:157
const char * func
Definition: Log.cpp:143
static std::atomic< bool > compact_output
Definition: Log.cpp:154
static std::atomic< bool > forward_backtrace
Definition: Log.cpp:161
static void call_current_forward_callback(yarp::os::Log::LogType type, const char *msg, const char *file, const unsigned int line, const char *func, double systemtime, double networktime, double externaltime, const char *comp_name, const char *id)
Definition: Log.cpp:119
static void do_log(yarp::os::Log::LogType type, const char *msg, const char *file, const unsigned int line, const char *func, double systemtime, double networktime, double externaltime, const LogComponent &comp_name, const std::string_view id)
Definition: Log.cpp:769
const LogComponent & comp
Definition: Log.cpp:148
static std::string quotedString(const std::string &x)
Definition: Storable.cpp:387
static long int getKeyOfCaller()
Definition: ThreadImpl.cpp:108
yarp::rosmsg::std_msgs::Time Time
Definition: Time.h:21
bool get_bool(const std::string &key, bool defaultValue=false)
Read a bool value from an environment variable.
Definition: environment.h:172
std::string to_hex_string(IntegerType i)
Definition: numeric.h:321
std::string to_string(IntegerType x)
Definition: numeric.h:115
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:121
bool isSystemClock()
Check if YARP is providing system time.
Definition: Time.cpp:262
void gethostname(char *hostname, size_t size)
Portable wrapper for the gethostname() function.
Definition: Os.cpp:97
The main, catch-all namespace for YARP.
Definition: dirs.h:16
The ProcessInfo struct provides the operating system process information.
Definition: SystemInfo.h:112
#define YARP_UNUSED(var)
Definition: api.h:162