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 
11 #include <yarp/os/LogComponent.h>
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 
21 #include <yarp/os/impl/Storable.h>
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 {
52 public:
53  LogPrivate(const char* file,
54  const unsigned int line,
55  const char* func,
56  const double externaltime,
58  const LogComponent& comp);
59 
60  void log(yarp::os::Log::LogType type,
61  const char *msg,
62  va_list args) const;
63 
65  const char* msg,
66  const char* file,
67  const unsigned int line,
68  const char* func,
69  double systemtime,
70  double networktime,
71  double externaltime,
72  const char* comp_name);
73 
75  const char* msg,
76  const char* file,
77  const unsigned int line,
78  const char* func,
79  double systemtime,
80  double networktime,
81  double externaltime,
82  const char* comp_name);
83 
84  // Calls the right print and forward callbacks
85  static void do_log(yarp::os::Log::LogType type,
86  const char* msg,
87  const char* file,
88  const unsigned int line,
89  const char* func,
90  double systemtime,
91  double networktime,
92  double externaltime,
93  const LogComponent& comp_name);
94 
95  // This is a LogCallback that calls the print callback that is currently
96  // set, even if this is changed later
98  const char* msg,
99  const char* file,
100  const unsigned int line,
101  const char* func,
102  double systemtime,
103  double networktime,
104  double externaltime,
105  const char* comp_name)
106  {
107  if (auto cb = current_print_callback.load()) {
108  cb(type, msg, file, line, func, systemtime, networktime, externaltime, comp_name);
109  }
110  }
111 
112  // This is a LogCallback that calls the forward callback that is currently
113  // set, even if this is changed later
115  const char* msg,
116  const char* file,
117  const unsigned int line,
118  const char* func,
119  double systemtime,
120  double networktime,
121  double externaltime,
122  const char* comp_name)
123  {
124  if (auto cb = current_forward_callback.load()) {
125  cb(type, msg, file, line, func, systemtime, networktime, externaltime, comp_name);
126  }
127  }
128 
130 
131 #ifdef YARP_HAS_WIN_VT_SUPPORT
132  bool enable_vt_colors();
133 #endif
134 
135  const char* file;
136  const unsigned int line;
137  const char* func;
138  double systemtime;
139  double networktime;
140  double externaltime;
143 
144  static std::atomic<bool> yarprun_format;
145  static std::atomic<bool> colored_output;
146  static std::atomic<bool> verbose_output;
147  static std::atomic<bool> compact_output;
148  static std::atomic<bool> debug_output;
149  static std::atomic<bool> trace_output;
150  static std::atomic<bool> forward_output;
151  static std::atomic<bool> forward_codeinfo;
152  static std::atomic<bool> forward_hostname;
153  static std::atomic<bool> forward_processinfo;
154  static std::atomic<bool> forward_backtrace;
155  static std::atomic<bool> debug_log;
156 #ifdef YARP_HAS_WIN_VT_SUPPORT
157  static std::atomic<bool> vt_colors_enabled;
158 #endif
159 
160  static std::atomic<yarp::os::Log::LogType> current_minimum_print_level;
161  static std::atomic<yarp::os::Log::LogType> current_minimum_forward_level;
162 
163  static std::atomic<Log::LogCallback> current_print_callback;
164  static std::atomic<Log::LogCallback> current_forward_callback;
165 
167 };
168 
169 // BEGIN Utilities
170 
171 #define BOLD_RED (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;31m" : "")
172 #define BOLD_GREEN (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;32m" : "")
173 #define BOLD_YELLOW (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;33m" : "")
174 #define BOLD_BLUE (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;34m" : "")
175 #define BOLD_MAGENTA (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;35m" : "")
176 #define BOLD_CYAN (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;36m" : "")
177 #define BOLD_WHITE (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[01;37m" : "")
178 #define RED (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[31m" : "")
179 #define GREEN (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[32m" : "")
180 #define YELLOW (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[33m" : "")
181 #define BLUE (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[34m" : "")
182 #define MAGENTA (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[35m" : "")
183 #define CYAN (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[36m" : "")
184 #define WHITE (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[37m" : "")
185 #define RED_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[41m" : "")
186 #define GREEN_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[42m" : "")
187 #define YELLOW_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[43m" : "")
188 #define BLUE_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[44m" : "")
189 #define MAGENTA_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[45m" : "")
190 #define CYAN_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[46m" : "")
191 #define WHITE_BG (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[47m" : "")
192 #define CLEAR (yarp::os::impl::LogPrivate::colored_output.load() ? "\033[00m" : "")
193 
194 namespace {
195 
196 inline const char* logTypeToString(yarp::os::Log::LogType t)
197 {
198  switch (t) {
200  return "TRACE";
202  return "DEBUG";
204  return "INFO";
206  return "WARNING";
208  return "ERROR";
210  return "FATAL";
211  default:
212  return "";
213  }
214 }
215 
216 inline const char* logTypeToColor(yarp::os::Log::LogType t)
217 {
218  switch (t) {
220  return BOLD_WHITE;
222  return BOLD_GREEN;
224  return BOLD_BLUE;
226  return BOLD_YELLOW;
228  return BOLD_RED;
230  return BOLD_WHITE;
232  return CYAN;
233  default:
234  return "";
235  }
236 }
237 
238 inline const char* logTypeToBgColor(yarp::os::Log::LogType t)
239 {
240  switch (t) {
242  return RED_BG;
248  default:
249  return "";
250  }
251 }
252 
253 inline const char* compNameToColor(const char* comp_name)
254 {
255  if (!comp_name || comp_name[0] == '\0' || !yarp::os::impl::LogPrivate::colored_output.load()) {
256  return "";
257  }
258 
259  // Hashing the component for every log line is probably not optimal, but in
260  // using a hash table will have the hash + a search, and since the
261  // LogCallback has only the name of the component, we cannot store the color
262  // in the LogComponent without breaking the API, therefore this is the less
263  // invasive option.
264  // Anyway, this is enabled only when YARP_COLORED_OUTPUT is set, therefore
265  // it can be easily disabled if this slows down the execution.
266  static std::hash<std::string> hsh; // FIXME C++17: Use string_view
267  std::size_t comp_hash = hsh(comp_name) % 12;
268  switch (comp_hash) {
269  case 0:
270  return RED;
271  case 1:
272  return BOLD_RED;
273  case 2:
274  return GREEN;
275  case 3:
276  return BOLD_GREEN;
277  case 4:
278  return YELLOW;
279  case 5:
280  return BOLD_YELLOW;
281  case 6:
282  return BLUE;
283  case 7:
284  return BOLD_BLUE;
285  case 8:
286  return MAGENTA;
287  case 9:
288  return BOLD_MAGENTA;
289  case 10:
290  return CYAN;
291  case 11:
292  return BOLD_CYAN;
293  default:
294  return "";
295  }
296 }
297 
298 std::string backtrace()
299 {
300 #ifdef YARP_HAS_ACE
301  ACE_Stack_Trace st(-1);
302  // TODO demangle symbols using <cxxabi.h> and abi::__cxa_demangle
303  // when available.
304  return {st.c_str()};
305 #elif defined(YARP_HAS_EXECINFO_H)
306  const size_t max_depth = 100;
307  size_t stack_depth;
308  void* stack_addrs[max_depth];
309  char** stack_strings;
310  stack_depth = ::backtrace(stack_addrs, max_depth);
311  stack_strings = backtrace_symbols(stack_addrs, stack_depth);
312  std::ostringstream ost;
313  for (size_t i = 1; i < stack_depth; i++) {
314  ost << stack_strings[i] << '\n';
315  }
316  free(stack_strings); // malloc()ed by backtrace_symbols
317  return ost.str();
318 #else
319  // Not implemented on this platform
320  return {};
321 #endif
322 }
323 
324 inline void forwardable_output(std::ostream* ost,
326  const char* msg,
327  const char* file,
328  const unsigned int line,
329  const char* func,
330  double systemtime,
331  double networktime,
332  double externaltime,
333  const char* comp_name)
334 {
335  const char *level = logTypeToString(t);
336 
337  // This generates the same string a Property containing the following keys:
338  // * level
339  // * systemtime
340  // * networktime (if not using system time)
341  // * externaltime (if defined)
342  // * filename (if YARP_FORWARD_CODEINFO_ENABLE is enabled)
343  // * line (if YARP_FORWARD_CODEINFO_ENABLE is enabled)
344  // * function (if YARP_FORWARD_CODEINFO_ENABLE is enabled)
345  // * hostname (if YARP_FORWARD_HOSTNAME_ENABLE is enabled)
346  // * cmd (if YARP_FORWARD_PROCESSINFO_ENABLE is enabled)
347  // * args (if YARP_FORWARD_PROCESSINFO_ENABLE is enabled)
348  // * pid (if YARP_FORWARD_PROCESSINFO_ENABLE is enabled)
349  // * thread_id (if YARP_FORWARD_PROCESSINFO_ENABLE is enabled)
350  // * component (if defined)
351  // * message (if any)
352  // * backtrace (for FATAL or if requested using YARP_FORWARD_BACKTRACE_ENABLE)
353 
354  *ost << "(level " << yarp::os::impl::StoreString::quotedString(level) << ")";
355  *ost << " (systemtime " << yarp::conf::numeric::to_string(systemtime) << ")";
357  *ost << " (networktime " << yarp::conf::numeric::to_string(networktime) << ")";
358  }
359  if (externaltime != 0.0) {
360  *ost << " (externaltime " << yarp::conf::numeric::to_string(externaltime) << ")";
361  }
363  *ost << " (filename " << yarp::os::impl::StoreString::quotedString(file) << ")";
364  *ost << " (line " << line << ")";
365  *ost << " (function " << yarp::os::impl::StoreString::quotedString(func) << ")";
366  }
368  static std::string hostname(yarp::os::gethostname());
369  *ost << " (hostname " << yarp::os::impl::StoreString::quotedString(hostname) << ")";
370  }
373  static std::string cmd(processInfo.name.substr(processInfo.name.find_last_of("\\/") + 1));
374  thread_local long thread_id(yarp::os::impl::ThreadImpl::getKeyOfCaller());
375  *ost << " (pid " << processInfo.pid << ")";
376  *ost << " (cmd " << yarp::os::impl::StoreString::quotedString(cmd) << ")";
377  *ost << " (args " << yarp::os::impl::StoreString::quotedString(processInfo.arguments) << ")";
378  *ost << " (thread_id 0x" << std::setfill('0') << std::setw(8) << yarp::conf::numeric::to_hex_string(thread_id) << ")";
379  }
380  if (comp_name) {
381  *ost << " (component " << yarp::os::impl::StoreString::quotedString(comp_name) << ")";
382  }
383  if (msg[0]) {
384  *ost << " (message " << yarp::os::impl::StoreString::quotedString(msg) << ")";
385  }
387  *ost << " (backtrace " << yarp::os::impl::StoreString::quotedString(backtrace()) << ")";
388  }
389 }
390 
391 inline void printable_output(std::ostream* ost,
393  const char* msg,
394  const char* file,
395  const unsigned int line,
396  const char* func,
397  double systemtime,
398  double networktime,
399  double externaltime,
400  const char* comp_name)
401 {
402  YARP_UNUSED(file);
403  YARP_UNUSED(line);
404  YARP_UNUSED(systemtime);
405  YARP_UNUSED(networktime);
406  YARP_UNUSED(externaltime);
407 
408 #if !defined (_MSC_VER)
409  static constexpr const char* level_char = u8"\u25CF";
410 #else
411  static constexpr const char* level_char = "*";
412 #endif
413 
414  const char* level_string = logTypeToString(t);
415  const char* level_color = logTypeToColor(t);
416  const char* level_bgcolor = logTypeToBgColor(t);
417  static const char *reserved_color = logTypeToColor(yarp::os::Log::LogTypeReserved);
418  const char* comp_color = compNameToColor(comp_name);
419 
420  // Print Level
422  *ost << level_color << level_bgcolor << level_char << CLEAR << " ";
423  } else {
424  *ost << "[" << level_color << level_bgcolor << level_string << CLEAR << "] ";
425  }
426 
427  // Print function information (trace only)
428  if (t == yarp::os::Log::TraceType) {
429  *ost << level_color << func << CLEAR << ((msg[0] || comp_name) ? ": " : "");
430  }
431 
432  // Print component
433  if (comp_name) {
434  *ost << "|" << comp_color << comp_name << CLEAR << "| ";
435  }
436 
437  // Finally print the message
439  *ost << reserved_color << '^' << CLEAR;
440  }
441  *ost << msg;
443  *ost << reserved_color << '$' << CLEAR;
444  }
445 }
446 
447 inline void printable_output_verbose(std::ostream* ost,
449  const char* msg,
450  const char* file,
451  const unsigned int line,
452  const char* func,
453  double systemtime,
454  double networktime,
455  double externaltime,
456  const char* comp_name)
457 {
458  YARP_UNUSED(systemtime);
459 
460  const char* level_string = logTypeToString(t);
461  const char *level_color = logTypeToColor(t);
462  const char *level_bgcolor = logTypeToBgColor(t);
463  static const char *reserved_color = logTypeToColor(yarp::os::Log::LogTypeReserved);
464  const char* comp_color = compNameToColor(comp_name);
465 
466  // Print external time
467  if (externaltime != 0.0) {
468  *ost << "[" << std::fixed << externaltime << "] ";
469  }
470  else {
471  // Print time
472  *ost << "[" << std::fixed << networktime << "] ";
473  }
474 
475  // Print level
476  *ost << "[" << level_color << level_bgcolor << level_string << CLEAR << "] ";
477 
478  // Print file, line and function
479  *ost << file << ":" << line << " " << level_color << level_bgcolor << func << CLEAR << " ";
480 
481  // Print thread id
482  *ost << "(0x" << std::setfill('0') << std::setw(8) << yarp::conf::numeric::to_hex_string(yarp::os::impl::ThreadImpl::getKeyOfCaller()) << ") ";
483 
484  // Print component
485  if (comp_name) {
486  *ost << "|" << comp_color << comp_name << CLEAR << "| ";
487  }
488 
489  // Finally print the message
491  *ost << reserved_color << '^' << CLEAR;
492  }
493  *ost << msg;
495  *ost << reserved_color << '$' << CLEAR;
496  }
497 }
498 
499 } // namespace
500 
501 // END Utilities
502 
503 // BEGIN LogPrivate static variables initialization
504 
505 // BEGIN Environment variables
506 std::atomic<bool> yarp::os::impl::LogPrivate::yarprun_format(yarp::conf::environment::get_bool("YARP_IS_YARPRUN", false) &&
507  yarp::conf::environment::get_bool("YARPRUN_IS_FORWARDING_LOG", false));
508 
509 #if defined(_WIN32) && !defined(YARP_HAS_WIN_VT_SUPPORT)
510 std::atomic<bool> yarp::os::impl::LogPrivate::colored_output(false);
511 #else
512 std::atomic<bool> yarp::os::impl::LogPrivate::colored_output(yarp::conf::environment::get_bool("YARP_COLORED_OUTPUT", false) &&
514 #endif
515 std::atomic<bool> yarp::os::impl::LogPrivate::verbose_output(yarp::conf::environment::get_bool("YARP_VERBOSE_OUTPUT", false) &&
517 std::atomic<bool> yarp::os::impl::LogPrivate::compact_output(yarp::conf::environment::get_bool("YARP_COMPACT_OUTPUT", false) &&
520 std::atomic<bool> yarp::os::impl::LogPrivate::forward_output(yarp::conf::environment::get_bool("YARP_FORWARD_LOG_ENABLE", false) &&
522 
523 // The following 4 environment variables are to be considered experimental
524 // until we have a reason to believe that this extra traffic does not impact
525 // on the performances (and that all these info are actually useful).
526 std::atomic<bool> yarp::os::impl::LogPrivate::forward_codeinfo(yarp::conf::environment::get_bool("YARP_FORWARD_CODEINFO_ENABLE", false));
527 std::atomic<bool> yarp::os::impl::LogPrivate::forward_hostname(yarp::conf::environment::get_bool("YARP_FORWARD_HOSTNAME_ENABLE", false));
528 std::atomic<bool> yarp::os::impl::LogPrivate::forward_processinfo(yarp::conf::environment::get_bool("YARP_FORWARD_PROCESSINFO_ENABLE", false));
529 std::atomic<bool> yarp::os::impl::LogPrivate::forward_backtrace(yarp::conf::environment::get_bool("YARP_FORWARD_BACKTRACE_ENABLE", false));
530 
531 std::atomic<bool> yarp::os::impl::LogPrivate::debug_output(yarp::conf::environment::get_bool("YARP_DEBUG_ENABLE", true));
532 std::atomic<bool> yarp::os::impl::LogPrivate::trace_output(yarp::conf::environment::get_bool("YARP_TRACE_ENABLE", false) &&
534 
535 std::atomic<bool> yarp::os::impl::LogPrivate::debug_log(yarp::conf::environment::get_bool("YARP_DEBUG_LOG_ENABLE", false));
536 // END Environment variables
537 
538 #ifdef YARP_HAS_WIN_VT_SUPPORT
539 std::atomic<bool> yarp::os::impl::LogPrivate::vt_colors_enabled = false;
540 #endif
541 
542 
543 std::atomic<yarp::os::Log::LogType> yarp::os::impl::LogPrivate::current_minimum_print_level(
547 
548 std::atomic<yarp::os::Log::LogType> yarp::os::impl::LogPrivate::current_minimum_forward_level(
551 
553 
554 std::atomic<yarp::os::Log::LogCallback> yarp::os::impl::LogPrivate::current_forward_callback(
556  : nullptr);
557 
558 // Log internal component never forwards the output and, if enabled, prints
559 // all the output using the default print callback
561  "yarp.os.Log",
566  : nullptr,
567  nullptr);
568 
569 
570 // END LogPrivate static variables initialization
571 
572 // BEGIN LogPrivate methods
573 
575  unsigned int line,
576  const char* func,
577  const double externaltime,
578  const yarp::os::Log::Predicate pred,
579  const LogComponent& comp) :
580  file(file),
581  line(line),
582  func(func),
583  systemtime(yarp::os::SystemClock::nowSystem()),
584  networktime(!yarp::os::NetworkBase::isNetworkInitialized() ? 0.0 : (yarp::os::Time::isSystemClock() ? systemtime : yarp::os::Time::now())),
585  externaltime(externaltime),
586  pred(pred),
587  comp(comp)
588 {
589 #ifdef YARP_HAS_WIN_VT_SUPPORT
590  if (colored_output.load() && !yarp::os::impl::LogPrivate::vt_colors_enabled.load()) {
591  colored_output = enable_vt_colors();
592  }
593 #endif
594 }
595 
597  const char* msg,
598  const char* file,
599  const unsigned int line,
600  const char* func,
601  double systemtime,
602  double networktime,
603  double externaltime,
604  const char* comp_name)
605 {
606  std::ostream *ost;
607  if(t == yarp::os::Log::TraceType ||
610  ost = &std::cout;
611  } else {
612  ost = &std::cerr;
613  }
614 
615  static std::mutex log_mutex;
616  std::lock_guard<std::mutex> lock(log_mutex);
617 
618  if (yarprun_format.load()) {
619  // Same output as forward_callback
620  forwardable_output(ost, t, msg, file, line, func, systemtime, networktime, externaltime, comp_name);
621  } else if (verbose_output.load()) {
622  printable_output_verbose(ost, t, msg, file, line, func, systemtime, networktime, externaltime, comp_name);
623  } else {
624  printable_output(ost, t, msg, file, line, func, systemtime, networktime, externaltime, comp_name);
625  }
626  *ost << std::endl;
627 }
628 
630  const char* msg,
631  const char* file,
632  const unsigned int line,
633  const char* func,
634  double systemtime,
635  double networktime,
636  double externaltime,
637  const char* comp_name)
638 {
640  // Network is not initialized. Don't forward any log.
641  // And avoid creating the LogForwarder!
642  return;
643  }
644  std::stringstream stringstream_buffer;
645  forwardable_output(&stringstream_buffer, t, msg, file, line, func, systemtime, networktime, externaltime, comp_name);
646  LogForwarder::getInstance().forward(stringstream_buffer.str());
647 }
648 
650  const char* msg,
651  va_list args) const
652 {
653  constexpr size_t YARP_MAX_STATIC_LOG_MSG_SIZE = 1024;
654 
655  if (msg != nullptr) {
656  if (!pred || pred()) {
657  char buf[YARP_MAX_STATIC_LOG_MSG_SIZE];
658  char* dyn_buf = nullptr;
659 
660  char* out = buf;
661  size_t buf_size = YARP_MAX_STATIC_LOG_MSG_SIZE;
662 
663  // Save va_list status in case we need to repeat the operation with
664  // the dynamically allocated buffer (vsnprintf leaves it in an
665  // undefined status).
666  va_list args_bak;
667  va_copy(args_bak, args);
668 
669  auto log_line_size = static_cast<size_t>(std::vsnprintf(buf, YARP_MAX_STATIC_LOG_MSG_SIZE, msg, args));
670 
671  if (log_line_size > YARP_MAX_STATIC_LOG_MSG_SIZE) {
672  // The static buffer is not big enough for the log line.
673  // Using a dynamic buffer instead.
674  // Round up size to the first power of 2.
675  size_t dyn_buf_size = [](size_t x) {
676  --x;
677  x |= x >> 1;
678  x |= x >> 2;
679  x |= x >> 4;
680  x |= x >> 8;
681  x |= x >> 16;
682  return x + 1;
683  }(log_line_size);
684 
685  dyn_buf = new char[dyn_buf_size];
686  std::vsnprintf(dyn_buf, dyn_buf_size, msg, args_bak);
687  va_end(args_bak);
688 
689  out = dyn_buf;
690  buf_size = dyn_buf_size;
691  }
692 
693  auto p = std::min(log_line_size - 1, buf_size);
694  if (log_line_size > 0 && p < buf_size && out[p] == '\n' && msg[strlen(msg) - 1] == '\n') {
695  yarp::os::Log(file, line, func, nullptr, log_internal_component).warning("Removing extra '\\n' (c-style)");
696  out[p] = 0;
697  }
698 
699  do_log(type, out, file, line, func, systemtime, networktime, externaltime, comp);
700 
701  if (dyn_buf) {
702  yarp::os::Log(file, line, func, nullptr, log_internal_component).warning("Previous message was longer than the static buffer size, dynamic allocation was used");
703  delete[] dyn_buf;
704  }
705  }
706  } else {
707  yarp::os::Log(file, line, func, nullptr, log_internal_component).warning("Unexpected nullptr received");
708  }
709 }
710 
712  const char* msg,
713  const char* file,
714  const unsigned int line,
715  const char* func,
716  double systemtime,
717  double networktime,
718  double externaltime,
719  const LogComponent& comp)
720 {
721  auto* print_cb = (yarprun_format && comp != log_internal_component) ? yarp::os::impl::LogPrivate::print_callback : comp.printCallback(type);
722  if (print_cb) {
723  print_cb(type, msg, file, line, func, systemtime, networktime, externaltime, comp.name());
724  } else {
725  if (comp != log_internal_component) {
726  if (comp.name()) {
727  yarp::os::Log(file, line, func, nullptr, log_internal_component).debug("Not printing [%s][%s]", comp.name(), msg);
728  } else {
729  yarp::os::Log(file, line, func, nullptr, log_internal_component).debug("Not printing [%s]", msg);
730  }
731  }
732  }
733 
734  auto* forward_cb = comp.forwardCallback(type);
735  if(forward_cb) {
736  forward_cb(type, msg, file, line, func, systemtime, networktime, externaltime, comp.name());
737  } else {
738  if (comp != log_internal_component) {
739  if (comp.name()) {
740  yarp::os::Log(file, line, func, nullptr, log_internal_component).debug("Not forwarding [%s][%s]", comp.name(), msg);
741  } else {
742  yarp::os::Log(file, line, func, nullptr, log_internal_component).debug("Not forwarding [%s]", msg);
743  }
744  }
745  }
746 }
747 
748 #ifdef YARP_HAS_WIN_VT_SUPPORT
749 bool yarp::os::impl::LogPrivate::enable_vt_colors()
750 {
751  DWORD handleMode = 0;
752  HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
753  bool success = false;
754 
755  if (hStdout != INVALID_HANDLE_VALUE && GetConsoleMode(hStdout, &handleMode)) {
756  handleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
757  success = SetConsoleMode(hStdout, handleMode);
758  }
759 
760  yarp::os::impl::LogPrivate::vt_colors_enabled = true;
761  return success;
762 }
763 #endif
764 
765 // END LogPrivate methods
766 
767 
768 // BEGIN Minimum Print Level
770 {
772 }
773 
775 {
777 }
778 
780 {
782 }
783 // END Minimum Print Level
784 
785 
786 // BEGIN Minimum Forward Level
788 {
791  }
792 }
793 
795 {
797 }
798 
800 {
802 }
803 
804 // END Minimum Forward Level
805 
806 
807 // BEGIN Print Callback
808 
809 #ifndef YARP_NO_DEPRECATED // Since YARP 3.4
811 {
813 }
814 #endif
815 
817 {
819 }
820 
822 {
824 }
825 
827 {
829 }
830 
831 // END Print Callback
832 
833 
834 // BEGIN Forward Callback
835 
837 {
840  }
841 }
842 
844 {
846 }
847 
849 {
851 }
852 
853 // END Forward Callback
854 
855 
856 // BEGIN Log Components
857 const yarp::os::LogComponent& yarp::os::Log::defaultLogComponent()
858 {
859  static const yarp::os::LogComponent component(nullptr,
860  minimumPrintLevel(),
861  minimumForwardLevel(),
862  printCallback(),
863  forwardCallback());
864  return component;
865 }
866 
867 const yarp::os::LogComponent& yarp::os::Log::logInternalComponent()
868 {
870 }
871 // END Log Components
872 
873 
874 yarp::os::Log::Log(const char* file,
875  unsigned int line,
876  const char* func,
877  const Predicate pred,
878  const LogComponent& comp) :
879  mPriv(new yarp::os::impl::LogPrivate(file, line, func, 0.0, pred, comp))
880 {
881 }
882 
883 // method for Log with externaltime
884 yarp::os::Log::Log(const char* file,
885  unsigned int line,
886  const char* func,
887  const double externaltime,
888  const Predicate pred,
889  const LogComponent& comp) :
890  mPriv(new yarp::os::impl::LogPrivate(file, line, func, externaltime, pred, comp))
891 {
892 }
893 
895  mPriv(new yarp::os::impl::LogPrivate(nullptr, 0, nullptr, 0.0, nullptr, nullptr))
896 {
897 }
898 
900 {
901  delete mPriv;
902 }
903 
904 void yarp::os::Log::do_log(yarp::os::Log::LogType type,
905  const char* msg,
906  const char* file,
907  const unsigned int line,
908  const char* func,
909  double systemtime,
910  double networktime,
911  double externaltime,
912  const LogComponent& comp)
913 {
914  yarp::os::impl::LogPrivate::do_log(type, msg, file, line, func, systemtime, networktime, externaltime, comp);
915 }
916 
917 
918 void yarp::os::Log::trace(const char* msg, ...) const
919 {
920  va_list args;
921  va_start(args, msg);
922  mPriv->log(yarp::os::Log::TraceType, msg, args);
923  va_end(args);
924 }
925 
927 {
929  mPriv->file,
930  mPriv->line,
931  mPriv->func,
932  mPriv->externaltime,
933  mPriv->pred,
934  mPriv->comp);
935 }
936 
937 
938 void yarp::os::Log::debug(const char* msg, ...) const
939 {
940  va_list args;
941  va_start(args, msg);
942  mPriv->log(yarp::os::Log::DebugType, msg, args);
943  va_end(args);
944 }
945 
947 {
949  mPriv->file,
950  mPriv->line,
951  mPriv->func,
952  mPriv->externaltime,
953  mPriv->pred,
954  mPriv->comp);
955 }
956 
957 void yarp::os::Log::info(const char* msg, ...) const
958 {
959  va_list args;
960  va_start(args, msg);
961  mPriv->log(yarp::os::Log::InfoType, msg, args);
962  va_end(args);
963 }
964 
966 {
968  mPriv->file,
969  mPriv->line,
970  mPriv->func,
971  mPriv->externaltime,
972  mPriv->pred,
973  mPriv->comp);
974 }
975 
976 
977 void yarp::os::Log::warning(const char* msg, ...) const
978 {
979  va_list args;
980  va_start(args, msg);
981  mPriv->log(yarp::os::Log::WarningType, msg, args);
982  va_end(args);
983 }
984 
986 {
988  mPriv->file,
989  mPriv->line,
990  mPriv->func,
991  mPriv->externaltime,
992  mPriv->pred,
993  mPriv->comp);
994 }
995 
996 
997 void yarp::os::Log::error(const char* msg, ...) const
998 {
999  va_list args;
1000  va_start(args, msg);
1001  mPriv->log(yarp::os::Log::ErrorType, msg, args);
1002  va_end(args);
1003 }
1004 
1006 {
1008  mPriv->file,
1009  mPriv->line,
1010  mPriv->func,
1011  mPriv->externaltime,
1012  mPriv->pred,
1013  mPriv->comp);
1014 }
1015 
1016 void yarp::os::Log::fatal(const char* msg, ...) const
1017 {
1018  va_list args;
1019  va_start(args, msg);
1020  mPriv->log(yarp::os::Log::FatalType, msg, args);
1021  va_end(args);
1022  yarp_print_trace(stderr, mPriv->file, mPriv->line);
1023  std::exit(-1);
1024 }
1025 
1027 {
1029  mPriv->file,
1030  mPriv->line,
1031  mPriv->func,
1032  mPriv->externaltime,
1033  mPriv->pred,
1034  mPriv->comp);
1035 }
1036 
1037 void yarp_print_trace(FILE* out, const char* file, unsigned int line)
1038 {
1039  fprintf(out, "Trace requested at %s:%u by code called from:\n", file, line);
1040  fprintf(out, "%s", backtrace().c_str());
1041  fflush(out);
1042 }
float t
#define BOLD_MAGENTA
Definition: Log.cpp:175
#define BOLD_BLUE
Definition: Log.cpp:174
#define BOLD_GREEN
Definition: Log.cpp:172
#define BOLD_YELLOW
Definition: Log.cpp:173
#define BOLD_RED
Definition: Log.cpp:171
#define CLEAR
Definition: Log.cpp:192
#define BOLD_CYAN
Definition: Log.cpp:176
#define MAGENTA
Definition: Log.cpp:182
#define BLUE
Definition: Log.cpp:181
#define RED
Definition: Log.cpp:178
#define BOLD_WHITE
Definition: Log.cpp:177
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:1037
#define YELLOW
Definition: Log.cpp:180
#define GREEN
Definition: Log.cpp:179
#define CYAN
Definition: Log.cpp:183
#define RED_BG
Definition: Log.cpp:185
void * HANDLE
constexpr const char * name() const
Definition: LogComponent.h:39
LogCallback printCallback(yarp::os::Log::LogType t) const
LogCallback forwardCallback(yarp::os::Log::LogType t) const
static void setLogCallback(LogCallback)
Definition: Log.cpp:810
LogStream trace() const
Definition: Log.cpp:926
static LogCallback printCallback()
Get current print callback.
Definition: Log.cpp:821
bool(*)() Predicate
Definition: Log.h:52
void warning(const char *msg,...) const
Definition: Log.cpp:977
static LogType defaultMinimumPrintLevel()
Get default minimum print level.
Definition: Log.cpp:779
virtual ~Log()
Definition: Log.cpp:899
void debug(const char *msg,...) const
Definition: Log.cpp:938
static LogType minimumPrintLevel()
Get current minimum print level.
Definition: Log.cpp:774
static LogCallback forwardCallback()
Get current forward callback (or nullptr if forwarding is not enabled)
Definition: Log.cpp:843
static LogType minimumForwardLevel()
Get current minimum forward level (or LogTypeReserved if forwarding is not enabled)
Definition: Log.cpp:794
LogStream error() const
Definition: Log.cpp:1005
LogStream warning() const
Definition: Log.cpp:985
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) LogCallback
Definition: Log.h:105
static void setPrintCallback(LogCallback)
Set current print callback.
Definition: Log.cpp:816
LogStream debug() const
Definition: Log.cpp:946
@ ErrorType
Definition: Log.h:78
@ LogTypeReserved
Definition: Log.h:80
@ DebugType
Definition: Log.h:75
@ TraceType
Definition: Log.h:74
@ InfoType
Definition: Log.h:76
@ FatalType
Definition: Log.h:79
@ WarningType
Definition: Log.h:77
static LogType defaultMinimumForwardLevel()
Get default minimum forward level (or LogTypeReserved if forwarding is not enabled)
Definition: Log.cpp:799
static void setForwardCallback(LogCallback)
Set current forward callback (it does nothing if forwarding is not enabled)
Definition: Log.cpp:836
LogStream fatal() const
Definition: Log.cpp:1026
static void setMinimumForwardLevel(LogType level)
Set current minimum forward level (it does nothing if forwarding is not enabled)
Definition: Log.cpp:787
static LogCallback defaultPrintCallback()
Get default print callback.
Definition: Log.cpp:826
LogStream info() const
Definition: Log.cpp:965
static LogCallback defaultForwardCallback()
Get default forward callback (or nullptr if forwarding is not enabled)
Definition: Log.cpp:848
static void setMinimumPrintLevel(LogType level)
Set current minimum print level.
Definition: Log.cpp:769
Utilities for manipulating the YARP network, excluding initialization and shutdown.
Definition: Network.h:41
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:152
static std::atomic< Log::LogCallback > current_forward_callback
Definition: Log.cpp:164
const unsigned int line
Definition: Log.cpp:136
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)
Definition: Log.cpp:629
static std::atomic< bool > debug_output
Definition: Log.cpp:148
void log(yarp::os::Log::LogType type, const char *msg, va_list args) const
Definition: Log.cpp:649
static std::atomic< bool > forward_codeinfo
Definition: Log.cpp:151
static std::atomic< yarp::os::Log::LogType > current_minimum_print_level
Definition: Log.cpp:160
static const LogComponent & logInternalComponent()
static std::atomic< bool > colored_output
Definition: Log.cpp:145
const char * file
Definition: Log.cpp:135
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)
Definition: Log.cpp:596
static std::atomic< Log::LogCallback > current_print_callback
Definition: Log.cpp:163
const yarp::os::Log::Predicate pred
Definition: Log.cpp:141
static std::atomic< bool > forward_processinfo
Definition: Log.cpp:153
static std::atomic< yarp::os::Log::LogType > current_minimum_forward_level
Definition: Log.cpp:161
static std::atomic< bool > trace_output
Definition: Log.cpp:149
static std::atomic< bool > verbose_output
Definition: Log.cpp:146
static std::atomic< bool > debug_log
Definition: Log.cpp:155
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)
Definition: Log.cpp:97
static const yarp::os::LogComponent log_internal_component
Definition: Log.cpp:166
static std::atomic< bool > yarprun_format
Definition: Log.cpp:144
static std::atomic< bool > forward_output
Definition: Log.cpp:150
const char * func
Definition: Log.cpp:137
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)
Definition: Log.cpp:114
static std::atomic< bool > compact_output
Definition: Log.cpp:147
static std::atomic< bool > forward_backtrace
Definition: Log.cpp:154
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)
Definition: Log.cpp:711
LogPrivate(const char *file, const unsigned int line, const char *func, const double externaltime, const yarp::os::Log::Predicate pred, const LogComponent &comp)
Definition: Log.cpp:574
const LogComponent & comp
Definition: Log.cpp:142
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:174
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:113
#define YARP_UNUSED(var)
Definition: api.h:162