MDL SDK API nvidia_logo_transpbg.gif Up
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ilogger.h
Go to the documentation of this file.
1 /***************************************************************************************************
2  * Copyright 2022 NVIDIA Corporation. All rights reserved.
3  **************************************************************************************************/
8 
9 #ifndef MI_BASE_ILOGGER_H
10 #define MI_BASE_ILOGGER_H
11 
12 #include <cstdarg>
13 #include <cstdio>
14 #include <ostream>
15 #include <sstream>
16 #include <string>
17 
18 #include <mi/base/config.h>
19 #include <mi/base/enums.h>
20 #include <mi/base/handle.h>
21 #include <mi/base/iinterface.h>
23 
24 namespace mi {
25 
26 namespace base {
27 
39 namespace details {
40 
43 // Tags may be combined.
45 {
46  TAG_NONE = 0u,
47  TAG_COMPATIBILITY = 1u << 0,
48  TAG_UNRECOVERABLE = 1u << 1,
49  TAG_API_INPUT = 1u << 2,
50  TAG_API_USAGE = 1u << 3,
51  TAG_VERSIONING = 1u << 4,
52  TAG_SYSTEM_RESOURCE = 1u << 5,
53  TAG_MEMORY = 1u << 6,
54  TAG_FILE = 1u << 7,
55  TAG_STATS = 1u << 8,
56  TAG_UNAVAILABLE = 1u << 9
57 };
58 
59 } // namespace details
60 
61 using namespace details;
62 
71 {
72  enum { HOST_ID_LOCAL = 0 };
73  enum {
74  DEVICE_ID_CPU = -1,
75  DEVICE_ID_UNKNOWN_CUDA = -2,
76  DEVICE_ID_ALL_CUDA = -3
77  };
78 
85 
88 
93 
96 
98  : host_id(HOST_ID_LOCAL)
99  , device_id(DEVICE_ID_CPU)
100  , tags(TAG_NONE)
101  , message_id(0u)
102  {}
103 
105  const Uint32 host,
106  const Sint32 device,
107  const Uint32 tag,
108  const Uint32 id)
109  : host_id(host)
110  , device_id(device)
111  , tags(tag)
112  , message_id(id)
113  {}
114 
116  bool is_device() const
117  {
118  return device_id != DEVICE_ID_CPU;
119  }
120 
122  bool is_tagged(const Uint32 required_tags) const
123  {
124  return (this->tags & required_tags) == required_tags;
125  }
126 
129  {
130  host_id = id;
131  return *this;
132  }
133 
136  {
137  device_id = id;
138  return *this;
139  }
140 
143  {
144  tags = t;
145  return *this;
146  }
147 
149  Message_details& tag(const Uint32 t, const Uint32 code)
150  {
151  tags = t;
152  message_id = code;
153  return *this;
154  }
155 
158  {
159  message_id = c;
160  return *this;
161  }
162 };
163 
164 
192 class ILogger : public
193  Interface_declare<0x4afbf19a,0x5fb7,0x4422,0xae,0x4b,0x25,0x13,0x06,0x2c,0x30,0x5f>
194 {
195 public:
215  virtual void message(
216  Message_severity level, const char* module_category, const char* message)
217 #ifdef MI_NEURAYLIB_DEPRECATED_LOG
218  = 0;
219 #else
220  {
221  this->message(level,module_category,Message_details(),message);
222  }
223 #endif
224 
229  virtual void message(
230  Message_severity level,
231  const char* module_category,
232  const Message_details&,
233  const char* message)
234 #ifdef MI_NEURAYLIB_DEPRECATED_LOG
235  {
236  this->message(level,module_category,message);
237  }
238 #else
239  = 0;
240 #endif
241 
263  inline void printf(
264  Message_severity level, const char* module_category, const char* message, ...)
265 #ifdef MI_COMPILER_GCC
266  __attribute__((format(printf, 4, 5)))
267 #endif
268  {
269  va_list args;
270  va_start( args, message);
271  char buffer[1024];
272 #ifdef MI_COMPILER_MSC
273  vsnprintf_s( &buffer[0], sizeof( buffer), sizeof( buffer)-1, message, args);
274 #else
275  vsnprintf( buffer, sizeof( buffer), message, args);
276 #endif
277  this->message( level, module_category, Message_details(), buffer);
278  va_end( args);
279  }
280 
285  inline void printf(
286  Message_severity level,
287  const char* module_category,
288  const Message_details& details,
289  const char* message,
290  ...)
291 #ifdef MI_COMPILER_GCC
292  __attribute__((format(printf, 5, 6)))
293 #endif
294  {
295  va_list args;
296  va_start( args, message);
297  char buffer[1024];
298 #ifdef MI_COMPILER_MSC
299  vsnprintf_s( buffer, sizeof( buffer), sizeof( buffer)-1, message, args);
300 #else
301  vsnprintf( buffer, sizeof( buffer), message, args);
302 #endif
303  this->message( level, module_category, details, buffer);
304  va_end( args);
305  }
306 };
307 
308 
309 class Log_stream;
310 
311 
312 // A specialization of std::stringbuf to be used together with #mi::base::Log_stream.
313 //
314 // Its sync() method is overridden to send the contents of the string buffer to the logger, and an
315 // additional method #set_log_level() allows to specify the log level of the next message.
316 class Log_streambuf : public std::stringbuf
317 {
318 public:
319  // Constructor.
320  //
321  // \param stream The stream used with this string buffer. Used to flush the stream
322  // if the log level is changed.
323  // \param module_category The module and the category which specify the origin and the
324  // functional area of this message. See #mi::base::ILogger::message()
325  // for details.
326  // \param default_level The default log level. Used if no other log level is selected by
327  // one of the manipulators.
328  // \param default_details The default message details. Used if no other details are set.
329  Log_streambuf(
330  Log_stream& stream,
331  const std::string& module_category,
332  Message_severity default_level = MESSAGE_SEVERITY_INFO,
333  const Message_details& default_details = Message_details())
334  : std::stringbuf( std::ios::out),
335  m_stream( stream),
336  m_default_level( default_level),
337  m_default_details( default_details),
338  m_module_category( module_category),
339  m_details( default_details)
340  {
341  set_log_level( m_default_level);
342  }
343 
344  // Destructor.
345  ~Log_streambuf() throw()
346  {
347  }
348 
349  // Flushes the string buffer if not empty, and sets the log level of the next message to the
350  // given log level.
351  void set_log_level( Message_severity level);
352 
353  // Flushes the string buffer if not empty, and sets the log level of the next message to the
354  // given log level.
355  void set_details( const Message_details& details);
356 
357 protected:
358 
359  // Sends the contents of the string buffer to the logger, clears the string buffer, and resets
360  // the log level and details to their defaults.
361  int sync();
362 
363 private:
364 
365  Log_stream& m_stream;
366  Message_severity m_default_level;
367  Message_details m_default_details;
368  std::string m_module_category;
369  Message_severity m_level;
370  Message_details m_details;
371 };
372 
389 class Log_stream : public std::ostream
390 {
391 public:
402  ILogger* logger,
403  const char* module_category,
404  Message_severity default_level = MESSAGE_SEVERITY_INFO,
405  const Message_details& default_details = Message_details())
406  : std::ostream( 0),
407  m_buffer( *this, module_category ? module_category : "APP:MAIN",
408  default_level, default_details),
409  m_logger( logger, DUP_INTERFACE)
410  {
411  rdbuf( &m_buffer);
412 #if (__cplusplus >= 201402L)
413  this->pword( get_index()) = this;
414 #endif
415  }
416 
427  ILogger* logger,
428  const std::string& module_category,
429  Message_severity default_level = MESSAGE_SEVERITY_INFO,
430  const Message_details& default_details = Message_details())
431  : std::ostream( 0),
432  m_buffer( *this, module_category, default_level, default_details),
433  m_logger( logger, DUP_INTERFACE)
434  {
435  rdbuf( &m_buffer);
436 #if (__cplusplus >= 201402L)
437  this->pword( get_index()) = this;
438 #endif
439  }
440 
444  ~Log_stream() throw()
445  {
446  flush();
447  }
448 
451  void set_log_level( Message_severity level) { m_buffer.set_log_level( level); }
452 
454  void set_details( const Message_details& details) { m_buffer.set_details( details); }
455 
456 #if (__cplusplus >= 201402L)
457  // Returns the unique index into the private storage of std::ios_base.
458  static int get_index()
459  {
460  // Static initialization is guaranteed to be thread-safe with C++11 and later. The method
461  // std::ios_base::xalloc() is guaranteed to be thread-safe with C++14 and later.
462  static const int s_index = std::ios_base::xalloc();
463  return s_index;
464  }
465 #endif
466 
467 private:
468  friend class Log_streambuf;
469 
470  Log_streambuf m_buffer;
471  mi::base::Handle<ILogger> m_logger;
472 
473  // Primary customization point.
474  // Note that this function may be called from the destructor.
475  virtual void message(
476  Message_severity level,
477  const char* module_category,
478  const Message_details& details,
479  const char* message) const
480  {
481  m_logger->message( level, module_category, details, message);
482  }
483 };
484 
485 
486 
487 inline void Log_streambuf::set_log_level( Message_severity level)
488 {
489  m_stream.flush();
490  m_level = level;
491 }
492 
493 inline void Log_streambuf::set_details( const Message_details& details)
494 {
495  m_stream.flush();
496  m_details = details;
497 }
498 
499 inline int Log_streambuf::sync()
500 {
501  std::stringbuf::sync();
502  const std::string& s = str();
503  if( !s.empty()) {
504  m_stream.message( m_level, m_module_category.c_str(), m_details, s.c_str());
505  str( "");
506  m_level = m_default_level;
507  m_details = m_default_details;
508  }
509  return 0;
510 }
511 
512 
522 template <typename C, typename T>
523 std::basic_ostream<C, T>& fatal( std::basic_ostream<C, T>& ostream)
524 {
525 #if (__cplusplus >= 201402L)
526  if( ostream.pword( Log_stream::get_index()) == &ostream)
527 #endif
528  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_FATAL);
529  return ostream;
530 }
531 
541 template <typename C, typename T>
542 std::basic_ostream<C, T>& error( std::basic_ostream<C, T>& ostream)
543 {
544 #if (__cplusplus >= 201402L)
545  if( ostream.pword( Log_stream::get_index()) == &ostream)
546 #endif
547  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_ERROR);
548  return ostream;
549 }
550 
560 template <typename C, typename T>
561 std::basic_ostream<C, T>& warning( std::basic_ostream<C, T>& ostream)
562 {
563 #if (__cplusplus >= 201402L)
564  if( ostream.pword( Log_stream::get_index()) == &ostream)
565 #endif
566  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_WARNING);
567  return ostream;
568 }
569 
579 template <typename C, typename T>
580 std::basic_ostream<C, T>& info( std::basic_ostream<C, T>& ostream)
581 {
582 #if (__cplusplus >= 201402L)
583  if( ostream.pword( Log_stream::get_index()) == &ostream)
584 #endif
585  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_INFO);
586  return ostream;
587 }
588 
598 template <typename C, typename T>
599 std::basic_ostream<C, T>& verbose( std::basic_ostream<C, T>& ostream)
600 {
601 #if (__cplusplus >= 201402L)
602  if( ostream.pword( Log_stream::get_index()) == &ostream)
603 #endif
604  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_VERBOSE);
605  return ostream;
606 }
607 
617 template <typename C, typename T>
618 std::basic_ostream<C, T>& debug( std::basic_ostream<C, T>& ostream)
619 {
620 #if (__cplusplus >= 201402L)
621  if( ostream.pword( Log_stream::get_index()) == &ostream)
622 #endif
623  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_DEBUG);
624  return ostream;
625 }
626 
635 template <typename C, typename T>
636 std::basic_ostream<C, T>& operator<<( std::basic_ostream<C, T>& ostream, const Message_details& md)
637 {
638 #if (__cplusplus >= 201402L)
639  if( ostream.pword( Log_stream::get_index()) == &ostream)
640 #endif
641  static_cast<Log_stream&>( ostream).set_details( md);
642  return ostream;
643 }
644 
645 
646 namespace msg {
647 
648 using namespace details;
649 typedef Message_tag Tag;
650 typedef Message_details Details;
651 
652 inline Details tag_details(const Uint32 tags)
653 {
654  return Details().tag(tags);
655 }
656 
657 inline Details device_details(
658  const Sint32 device=Details::DEVICE_ID_UNKNOWN_CUDA,
659  const Uint32 tags=TAG_NONE)
660 {
661  return Details().tag(tags).device(device);
662 }
663 
664 }
665  // end group mi_base_ilogger
667 
668 } // namespace base
669 
670 } // namespace mi
671 
672 #endif // MI_BASE_ILOGGER_H