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