YARP
Yet Another Robot Platform
Log.h
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 #ifndef YARP_OS_LOG_H
7 #define YARP_OS_LOG_H
8 
9 #include <yarp/os/api.h>
10 
11 #include <cstdint>
12 #include <iosfwd>
13 #include <mutex>
14 
15 #if defined(__GNUC__)
16 # define __YFUNCTION__ __PRETTY_FUNCTION__
17 #elif defined(_MSC_VER)
18 # define __YFUNCTION__ __FUNCSIG__
19 #elif (__cplusplus <= 199711)
20 # define __YFUNCTION__ __func__
21 #else
22 # define __YFUNCTION__ "(unknown function)"
23 #endif // __GNUC__
24 
25 // check arguments of the c-style debug functions to make sure that the
26 // arguments supplied have types appropriate to the format string
27 // specified, and that the conversions specified in the format string
28 // make sense. On gcc the warning is enabled by -Wformat.
29 #if defined(__GNUC__)
30 # define YARP_ATTRIBUTE_FORMAT(style, fmt, args) __attribute__((format(printf, (fmt), (args))))
31 #else
32 # define YARP_ATTRIBUTE_FORMAT(style, fmt, args)
33 #endif
34 
35 
36 // Forward declarations
37 namespace yarp {
38 namespace os {
39 
40 class LogComponent;
41 class LogStream;
42 
43 #ifndef DOXYGEN_SHOULD_SKIP_THIS
44 namespace impl {
45 class LogPrivate;
46 } // namespace impl
47 #endif // DOXYGEN_SHOULD_SKIP_THIS
48 
50 {
51 public:
52  using Predicate = bool(*)();
53 
54  Log(const char* file,
55  const unsigned int line,
56  const char* func,
57  const Predicate pred = nullptr,
58  const LogComponent& comp = defaultLogComponent());
59 
60  // constructor with externaltime
61  Log(const char* file,
62  const unsigned int line,
63  const char* func,
64  const double externaltime,
65  const Predicate pred = nullptr,
66  const LogComponent& comp = defaultLogComponent());
67 
68  Log();
69  virtual ~Log();
70 
71  enum LogType : uint8_t
72  {
73  LogTypeUnknown = 0,
80  LogTypeReserved = 0xFF
81  };
82 
83  void trace(const char* msg, ...) const YARP_ATTRIBUTE_FORMAT(printf, 2, 3);
84  void debug(const char* msg, ...) const YARP_ATTRIBUTE_FORMAT(printf, 2, 3);
85  void info(const char* msg, ...) const YARP_ATTRIBUTE_FORMAT(printf, 2, 3);
86  void warning(const char* msg, ...) const YARP_ATTRIBUTE_FORMAT(printf, 2, 3);
87  void error(const char* msg, ...) const YARP_ATTRIBUTE_FORMAT(printf, 2, 3);
88  YARP_NORETURN void fatal(const char* msg, ...) const YARP_ATTRIBUTE_FORMAT(printf, 2, 3);
89 
90  LogStream trace() const;
91  LogStream debug() const;
92  LogStream info() const;
93  LogStream warning() const;
94  LogStream error() const;
95  LogStream fatal() const;
96 
97  using LogCallback = void (*)(yarp::os::Log::LogType type,
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 #ifndef YARP_NO_DEPRECATED // Since YARP 3.4
108  YARP_DEPRECATED_MSG("Use setPrintCallback instead")
109  static void setLogCallback(LogCallback);
110 #endif // YARP_NO_DEPRECATED
111 
112  static void setMinimumPrintLevel(LogType level);
113  static LogType minimumPrintLevel();
114  static LogType defaultMinimumPrintLevel();
115 
116  static void setMinimumForwardLevel(LogType level);
117  static LogType minimumForwardLevel();
118  static LogType defaultMinimumForwardLevel();
119 
120  static void setPrintCallback(LogCallback);
121  static LogCallback printCallback();
122  static LogCallback defaultPrintCallback();
123 
124  static void setForwardCallback(LogCallback);
125  static LogCallback forwardCallback();
126  static LogCallback defaultForwardCallback();
127 
128 
129 #ifndef DOXYGEN_SHOULD_SKIP_THIS
130  static void nolog(const char* msg, ...) {}
131  struct NoLog
132  {
133  template <typename T>
134  NoLog& operator<<(const T&)
135  {
136  return *this;
137  }
138  };
139  static NoLog nolog() { return NoLog(); }
140 
141 private:
142  yarp::os::impl::LogPrivate* const mPriv;
143 
144  friend class yarp::os::LogStream;
145 
146  // This callback is called by LogStream
147  static void do_log(yarp::os::Log::LogType type,
148  const char* msg,
149  const char* file,
150  const unsigned int line,
151  const char* func,
152  double systemtime,
153  double networktime,
154  double externaltime,
155  const LogComponent& comp_name);
156 
157  // This component is used for yDebug-family output, and is called by LogStream
158  static const LogComponent& defaultLogComponent();
159 
160  // This component is used for internal debug output, and is called by LogStream
161  static const LogComponent& logInternalComponent();
162 #endif // DOXYGEN_SHOULD_SKIP_THIS
163 }; // class Log
164 
165 } // namespace os
166 } // namespace yarp
167 
168 
169 
170 
171 #define YARP_ONCE_CALLBACK \
172  [](){ \
173  static std::atomic_flag flag = ATOMIC_FLAG_INIT; \
174  return !flag.test_and_set(); \
175  }
176 
177 #define YARP_THREADONCE_CALLBACK \
178  [](){ \
179  thread_local std::atomic_flag flag = ATOMIC_FLAG_INIT; \
180  return !flag.test_and_set(); \
181  }
182 
183 #define YARP_THROTTLE_CALLBACK(period) \
184  [](){ \
185  static double last = -period; \
186  static std::mutex mutex; \
187  std::lock_guard<std::mutex> lock(mutex); \
188  double now = yarp::os::SystemClock::nowSystem(); \
189  if (now >= last + period) { \
190  last = now; \
191  return true; \
192  } \
193  return false; \
194  }
195 
196 #define YARP_THREADTHROTTLE_CALLBACK(period) \
197  [](){ \
198  thread_local double last = -period; \
199  double now = yarp::os::SystemClock::nowSystem(); \
200  if (now >= last + period) { \
201  last = now; \
202  return true; \
203  } \
204  return false; \
205  }
206 
207 
208 
209 #ifndef NDEBUG
210 # define yTrace(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__).trace(__VA_ARGS__)
211 # define yTraceOnce(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_ONCE_CALLBACK).trace(__VA_ARGS__)
212 # define yTraceThreadOnce(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THREADONCE_CALLBACK).trace(__VA_ARGS__)
213 # define yTraceThrottle(period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THROTTLE_CALLBACK(period)).trace(__VA_ARGS__)
214 # define yTraceThreadThrottle(period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THREADTHROTTLE_CALLBACK(period)).trace(__VA_ARGS__)
215 # define yTraceExternalTime(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime).trace(__VA_ARGS__)
216 # define yTraceExternalTimeOnce(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_ONCE_CALLBACK).trace(__VA_ARGS__)
217 # define yTraceExternalTimeThreadOnce(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THREADONCE_CALLBACK).trace(__VA_ARGS__)
218 # define yTraceExternalTimeThrottle(externaltime, period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THROTTLE_CALLBACK(period)).trace(__VA_ARGS__)
219 # define yTraceExternalTimeThreadThrottle(externaltime, period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THREADTHROTTLE_CALLBACK(period)).trace(__VA_ARGS__)
220 #else
221 # define yTrace(...) yarp::os::Log::nolog(__VA_ARGS__)
222 # define yTraceOnce(...) yarp::os::Log::nolog(__VA_ARGS__)
223 # define yTraceThreadOnce(...) yarp::os::Log::nolog(__VA_ARGS__)
224 # define yTraceThrottle(period, ...) yarp::os::Log::nolog(__VA_ARGS__)
225 # define yTraceThreadThrottle(period, ...) yarp::os::Log::nolog(__VA_ARGS__)
226 # define yTraceExternalTime(externaltime, ...) yarp::os::Log::nolog(__VA_ARGS__)
227 # define yTraceExternalTimeOnce(externaltime, ...) yarp::os::Log::nolog(__VA_ARGS__)
228 # define yTraceExternalTimeThreadOnce(externaltime, ...) yarp::os::Log::nolog(__VA_ARGS__)
229 # define yTraceExternalTimeThrottle(externaltime, period, ...) yarp::os::Log::nolog(__VA_ARGS__)
230 # define yTraceExternalTimeThreadThrottle(externaltime, period, ...) yarp::os::Log::nolog(__VA_ARGS__)
231 #endif
232 
233 #ifndef YARP_NO_DEBUG_OUTPUT
234 # define yDebug(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__).debug(__VA_ARGS__)
235 # define yDebugOnce(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_ONCE_CALLBACK).debug(__VA_ARGS__)
236 # define yDebugThreadOnce(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THREADONCE_CALLBACK).debug(__VA_ARGS__)
237 # define yDebugThrottle(period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THROTTLE_CALLBACK(period)).debug(__VA_ARGS__)
238 # define yDebugThreadThrottle(period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THREADTHROTTLE_CALLBACK(period)).debug(__VA_ARGS__)
239 # define yDebugExternalTime(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime).debug(__VA_ARGS__)
240 # define yDebugExternalTimeOnce(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_ONCE_CALLBACK).debug(__VA_ARGS__)
241 # define yDebugExternalTimeThreadOnce(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THREADONCE_CALLBACK).debug(__VA_ARGS__)
242 # define yDebugExternalTimeThrottle(externaltime, period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THROTTLE_CALLBACK(period)).debug(__VA_ARGS__)
243 # define yDebugExternalTimeThreadThrottle(externaltime, period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THREADTHROTTLE_CALLBACK(period)).debug(__VA_ARGS__)
244 #else
245 # define yDebug(...) yarp::os::Log::nolog(__VA_ARGS__)
246 # define yDebugOnce(...) yarp::os::Log::nolog(__VA_ARGS__)
247 # define yDebugThreadOnce(...) yarp::os::Log::nolog(__VA_ARGS__)
248 # define yDebugThrottle(period, ...) yarp::os::Log::nolog(__VA_ARGS__)
249 # define yDebugThreadThrottle(period, ...) yarp::os::Log::nolog(__VA_ARGS__)
250 # define yDebugExternalTime(externaltime, ...) yarp::os::Log::nolog(__VA_ARGS__)
251 # define yDebugExternalTimeOnce(externaltime, ...) yarp::os::Log::nolog(__VA_ARGS__)
252 # define yDebugExternalTimeThreadOnce(externaltime, ...) yarp::os::Log::nolog(__VA_ARGS__)
253 # define yDebugExternalTimeThrottle(externaltime, period, ...) yarp::os::Log::nolog(__VA_ARGS__)
254 # define yDebugExternalTimeThreadThrottle(externaltime, period, ...) yarp::os::Log::nolog(__VA_ARGS__)
255 #endif
256 
257 #define yInfo(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__).info(__VA_ARGS__)
258 #define yInfoOnce(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_ONCE_CALLBACK).info(__VA_ARGS__)
259 #define yInfoThreadOnce(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THREADONCE_CALLBACK).info(__VA_ARGS__)
260 #define yInfoThrottle(period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THROTTLE_CALLBACK(period)).info(__VA_ARGS__)
261 #define yInfoThreadThrottle(period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THREADTHROTTLE_CALLBACK(period)).info(__VA_ARGS__)
262 #define yInfoExternalTime(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime).info(__VA_ARGS__)
263 #define yInfoExternalTimeOnce(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_ONCE_CALLBACK).info(__VA_ARGS__)
264 #define yInfoExternalTimeThreadOnce(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THREADONCE_CALLBACK).info(__VA_ARGS__)
265 #define yInfoExternalTimeThrottle(externaltime, period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THROTTLE_CALLBACK(period)).info(__VA_ARGS__)
266 #define yInfoExternalTimeThreadThrottle(externaltime, period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THREADTHROTTLE_CALLBACK(period)).info(__VA_ARGS__)
267 
268 #define yWarning(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__).warning(__VA_ARGS__)
269 #define yWarningOnce(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_ONCE_CALLBACK).warning(__VA_ARGS__)
270 #define yWarningThreadOnce(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THREADONCE_CALLBACK).warning(__VA_ARGS__)
271 #define yWarningThrottle(period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THROTTLE_CALLBACK(period)).warning(__VA_ARGS__)
272 #define yWarningThreadThrottle(period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THREADTHROTTLE_CALLBACK(period)).warning(__VA_ARGS__)
273 #define yWarningExternalTime(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime).warning(__VA_ARGS__)
274 #define yWarningExternalTimeOnce(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_ONCE_CALLBACK).warning(__VA_ARGS__)
275 #define yWarningExternalTimeThreadOnce(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THREADONCE_CALLBACK).warning(__VA_ARGS__)
276 #define yWarningExternalTimeThrottle(externaltime, period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THROTTLE_CALLBACK(period)).warning(__VA_ARGS__)
277 #define yWarningExternalTimeThreadThrottle(externaltime, period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THREADTHROTTLE_CALLBACK(period)).warning(__VA_ARGS__)
278 
279 #define yError(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__).error(__VA_ARGS__)
280 #define yErrorOnce(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_ONCE_CALLBACK).error(__VA_ARGS__)
281 #define yErrorThreadOnce(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THREADONCE_CALLBACK).error(__VA_ARGS__)
282 #define yErrorThrottle(period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THROTTLE_CALLBACK(period)).error(__VA_ARGS__)
283 #define yErrorThreadThrottle(period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, YARP_THREADTHROTTLE_CALLBACK(period)).error(__VA_ARGS__)
284 #define yErrorExternalTime(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime).error(__VA_ARGS__)
285 #define yErrorExternalTimeOnce(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_ONCE_CALLBACK).error(__VA_ARGS__)
286 #define yErrorExternalTimeThreadOnce(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THREADONCE_CALLBACK).error(__VA_ARGS__)
287 #define yErrorExternalTimeThrottle(externaltime, period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THROTTLE_CALLBACK(period)).error(__VA_ARGS__)
288 #define yErrorExternalTimeThreadThrottle(externaltime, period, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime, YARP_THREADTHROTTLE_CALLBACK(period)).error(__VA_ARGS__)
289 
290 #define yFatal(...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__).fatal(__VA_ARGS__)
291 #define yFatalExternalTime(externaltime, ...) yarp::os::Log(__FILE__, __LINE__, __YFUNCTION__, externaltime).fatal(__VA_ARGS__)
292 
293 #ifndef NDEBUG
294 # define yAssert(x) \
295  if (!(x)) { \
296  yFatal("Assertion failure at %s:%d (%s)", __FILE__, __LINE__, #x); \
297  }
298 # define yAssertExternalTime(externaltime, x) \
299  if (!(x)) { \
300  yFatalExternalTime(externaltime, "Assertion failure at %s:%d (%s)", __FILE__, __LINE__, #x); \
301  }
302 #else
303 # define yAssert(x)
304 # define yAssertExternalTime(externaltime, x) { YARP_UNUSED(externaltime); }
305 #endif
306 
307 #define YARP_FIXME_NOTIMPLEMENTED(what) yWarning("FIXME: %s not yet implemented", what);
308 
309 
313 YARP_os_API void yarp_print_trace(FILE* out, const char* file, unsigned int line);
314 
315 
316 #endif // YARP_OS_LOG_H
#define YARP_ATTRIBUTE_FORMAT(style, fmt, args)
Definition: Log.h:32
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:1065
bool(*)() Predicate
Definition: Log.h:52
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
@ ErrorType
Definition: Log.h:78
@ 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
#define YARP_DEPRECATED_MSG(MSG)
Expands to either the standard [[deprecated]] attribute or a compiler-specific decorator such as __at...
Definition: compiler.h:2885
The main, catch-all namespace for YARP.
Definition: dirs.h:16
std::ostream & operator<<(std::ostream &os, StrStream &sstr)
Definition: utility.cpp:86
#define YARP_NORETURN
Definition: api.h:156
#define YARP_os_API
Definition: api.h:18