YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
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,
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()) {
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()) {
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[] = "\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)
464 if (t == yarp::os::Log::TraceType) {
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(
599 (!yarp::os::impl::LogPrivate::debug_output.load() ? yarp::os::Log::InfoType :
600 yarp::os::Log::defaultMinimumPrintLevel())));
601
602std::atomic<yarp::os::Log::LogType> yarp::os::impl::LogPrivate::current_minimum_forward_level(
604 : yarp::os::Log::LogTypeReserved);
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",
617 : yarp::os::Log::LogTypeReserved,
618 yarp::os::Log::LogTypeReserved,
619 yarp::os::impl::LogPrivate::debug_log.load() ? yarp::os::impl::LogPrivate::call_current_print_callback
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()) {
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;
664 if(t == yarp::os::Log::TraceType ||
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);
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()) {
716 char* dyn_buf = nullptr;
717
718 char* out = buf;
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).
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
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);
746
747 out = dyn_buf;
749 }
750
751 auto p = std::min<size_t>(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;
812 bool success = false;
813
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
832
837
842// END Minimum Print Level
843
844
845// BEGIN Minimum Forward Level
852
857
862
863// END Minimum Forward Level
864
865
866// BEGIN Print Callback
867
872
877
882
883// END Print Callback
884
885
886// BEGIN Forward Callback
887
894
899
904
905// END Forward Callback
906
907
908// BEGIN Log Components
909const yarp::os::LogComponent& yarp::os::Log::defaultLogComponent()
910{
911 static const yarp::os::LogComponent component(nullptr,
912 minimumPrintLevel(),
913 minimumForwardLevel(),
914 printCallback(),
915 forwardCallback());
916 return component;
917}
918
919const yarp::os::LogComponent& yarp::os::Log::logInternalComponent()
920{
922}
923// END Log Components
924
925
926yarp::os::Log::Log(const char* file,
927 unsigned int line,
928 const char* func,
929 const Predicate pred,
930 const LogComponent& comp) :
931 mPriv(std::make_unique<yarp::os::impl::LogPrivate>(file, line, func, "", 0.0, pred, comp))
932{
933}
934
935// method for Log with id
936yarp::os::Log::Log(const char* file,
937 unsigned int line,
938 const char* func,
939 std::string_view id,
940 const Predicate pred,
941 const LogComponent& comp) :
942 mPriv(std::make_unique<yarp::os::impl::LogPrivate>(file, line, func, id.data(), 0.0, pred, comp))
943{
944}
945
946// method for Log with externaltime
947yarp::os::Log::Log(const char* file,
948 unsigned int line,
949 const char* func,
950 const double externaltime,
951 const Predicate pred,
952 const LogComponent& comp) :
953 mPriv(std::make_unique<yarp::os::impl::LogPrivate>(file, line, func, "", externaltime, pred, comp))
954{
955}
956
957// method for Log with id and externaltime
958
959yarp::os::Log::Log(const char* file,
960 unsigned int line,
961 const char* func,
962 std::string_view id,
963 const double externaltime,
964 const Predicate pred,
965 const LogComponent& comp) :
966 mPriv(std::make_unique<yarp::os::impl::LogPrivate>(file, line, func, id.data(), externaltime, pred, comp))
967{
968}
969
971 mPriv(std::make_unique<yarp::os::impl::LogPrivate>(nullptr, 0, nullptr, nullptr, 0.0, nullptr, nullptr))
972{
973}
974
978
979void yarp::os::Log::do_log(yarp::os::Log::LogType type,
980 const char* msg,
981 const char* file,
982 const unsigned int line,
983 const char* func,
984 double systemtime,
985 double networktime,
986 double externaltime,
987 const LogComponent& comp,
988 const std::string_view id)
989{
990 yarp::os::impl::LogPrivate::do_log(type, msg, file, line, func, systemtime, networktime, externaltime, comp, id);
991}
992
993
994void yarp::os::Log::trace(const char* msg, ...) const
995{
996 va_list args;
997 va_start(args, msg);
998 mPriv->log(yarp::os::Log::TraceType, msg, args);
999 va_end(args);
1000}
1001
1003{
1005 mPriv->file,
1006 mPriv->line,
1007 mPriv->func,
1008 mPriv->id,
1009 mPriv->externaltime,
1010 mPriv->pred,
1011 mPriv->comp);
1012}
1013
1014
1015void yarp::os::Log::debug(const char* msg, ...) const
1016{
1017 va_list args;
1018 va_start(args, msg);
1019 mPriv->log(yarp::os::Log::DebugType, msg, args);
1020 va_end(args);
1021}
1022
1024{
1026 mPriv->file,
1027 mPriv->line,
1028 mPriv->func,
1029 mPriv->id,
1030 mPriv->externaltime,
1031 mPriv->pred,
1032 mPriv->comp);
1033}
1034
1035void yarp::os::Log::info(const char* msg, ...) const
1036{
1037 va_list args;
1038 va_start(args, msg);
1039 mPriv->log(yarp::os::Log::InfoType, msg, args);
1040 va_end(args);
1041}
1042
1044{
1046 mPriv->file,
1047 mPriv->line,
1048 mPriv->func,
1049 mPriv->id,
1050 mPriv->externaltime,
1051 mPriv->pred,
1052 mPriv->comp);
1053}
1054
1055
1056void yarp::os::Log::warning(const char* msg, ...) const
1057{
1058 va_list args;
1059 va_start(args, msg);
1060 mPriv->log(yarp::os::Log::WarningType, msg, args);
1061 va_end(args);
1062}
1063
1065{
1067 mPriv->file,
1068 mPriv->line,
1069 mPriv->func,
1070 mPriv->id,
1071 mPriv->externaltime,
1072 mPriv->pred,
1073 mPriv->comp);
1074}
1075
1076
1077void yarp::os::Log::error(const char* msg, ...) const
1078{
1079 va_list args;
1080 va_start(args, msg);
1081 mPriv->log(yarp::os::Log::ErrorType, msg, args);
1082 va_end(args);
1083}
1084
1086{
1088 mPriv->file,
1089 mPriv->line,
1090 mPriv->func,
1091 mPriv->id,
1092 mPriv->externaltime,
1093 mPriv->pred,
1094 mPriv->comp);
1095}
1096
1097void yarp::os::Log::fatal(const char* msg, ...) const
1098{
1099 va_list args;
1100 va_start(args, msg);
1101 mPriv->log(yarp::os::Log::FatalType, msg, args);
1102 va_end(args);
1103 yarp_print_trace(stderr, mPriv->file, mPriv->line);
1104 std::exit(-1);
1105}
1106
1108{
1110 mPriv->file,
1111 mPriv->line,
1112 mPriv->func,
1113 mPriv->id,
1114 mPriv->externaltime,
1115 mPriv->pred,
1116 mPriv->comp);
1117}
1118
1119void yarp_print_trace(FILE* out, const char* file, unsigned int line)
1120{
1121 fprintf(out, "Trace requested at %s:%u by code called from:\n", file, line);
1122 fprintf(out, "%s", backtrace().c_str());
1123 fflush(out);
1124}
#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:1119
#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
A mini-server for performing network communication in the background.
constexpr const char * name() const
LogCallback printCallback(yarp::os::Log::LogType t) const
LogCallback forwardCallback(yarp::os::Log::LogType t) const
LogStream trace() const
Definition Log.cpp:1002
static LogCallback printCallback()
Get current print callback.
Definition Log.cpp:873
void warning(const char *msg,...) const
Definition Log.cpp:1056
static LogType defaultMinimumPrintLevel()
Get default minimum print level.
Definition Log.cpp:838
virtual ~Log()
Definition Log.cpp:975
void debug(const char *msg,...) const
Definition Log.cpp:1015
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:895
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:1085
LogStream warning() const
Definition Log.cpp:1064
static void setPrintCallback(LogCallback)
Set current print callback.
Definition Log.cpp:868
LogStream debug() const
Definition Log.cpp:1023
@ ErrorType
Definition Log.h:96
@ LogTypeReserved
Definition Log.h:98
@ DebugType
Definition Log.h:93
@ TraceType
Definition Log.h:92
@ InfoType
Definition Log.h:94
@ FatalType
Definition Log.h:97
@ WarningType
Definition Log.h:95
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:888
LogStream fatal() const
Definition Log.cpp:1107
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:878
LogStream info() const
Definition Log.cpp:1043
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:130
static LogCallback defaultForwardCallback()
Get default forward callback (or nullptr if forwarding is not enabled)
Definition Log.cpp:900
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.
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
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
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()
STL namespace.
bool get_bool(const std::string &key, bool defaultValue=false)
Read a bool value from an environment variable.
std::string to_hex_string(IntegerType i)
Definition numeric.h:321
std::string to_string(IntegerType x)
Definition numeric.h:115
bool isSystemClock()
Check if YARP is providing system time.
Definition Time.cpp:255
std::string gethostname()
Portable wrapper for the gethostname() function.
Definition Os.cpp:98
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