NVIDIA IndeX: Base 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 2020 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 };
57 
58 } // namespace details
59 
60 using namespace details;
61 
70 {
71  enum { HOST_ID_LOCAL = 0 };
72  enum {
73  DEVICE_ID_CPU = -1,
74  DEVICE_ID_UNKNOWN_CUDA = -2
75  };
76 
83 
86 
91 
94 
96  : host_id(HOST_ID_LOCAL)
97  , device_id(DEVICE_ID_CPU)
98  , tags(TAG_NONE)
99  , message_id(0u)
100  {}
101 
103  const Uint32 host,
104  const Sint32 device,
105  const Uint32 tag,
106  const Uint32 id)
107  : host_id(host)
108  , device_id(device)
109  , tags(tag)
110  , message_id(id)
111  {}
112 
114  bool is_device() const
115  {
116  return device_id != DEVICE_ID_CPU;
117  }
118 
120  bool is_tagged(const Uint32 required_tags) const
121  {
122  return (this->tags & required_tags) == required_tags;
123  }
124 
127  {
128  host_id = id;
129  return *this;
130  }
131 
134  {
135  device_id = id;
136  return *this;
137  }
138 
141  {
142  tags = t;
143  return *this;
144  }
145 
147  Message_details& tag(const Uint32 t, const Uint32 code)
148  {
149  tags = t;
150  message_id = code;
151  return *this;
152  }
153 
156  {
157  message_id = c;
158  return *this;
159  }
160 };
161 
162 
190 class ILogger : public
191  Interface_declare<0x4afbf19a,0x5fb7,0x4422,0xae,0x4b,0x25,0x13,0x06,0x2c,0x30,0x5f>
192 {
193 public:
213  virtual void message(
214  Message_severity level, const char* module_category, const char* message)
215 #ifdef MI_NEURAYLIB_DEPRECATED_LOG
216  = 0;
217 #else
218  {
219  this->message(level,module_category,Message_details(),message);
220  }
221 #endif
222 
227  virtual void message(
228  Message_severity level,
229  const char* module_category,
230  const Message_details&,
231  const char* message)
232 #ifdef MI_NEURAYLIB_DEPRECATED_LOG
233  {
234  this->message(level,module_category,message);
235  }
236 #else
237  = 0;
238 #endif
239 
261  inline void printf(
262  Message_severity level, const char* module_category, const char* message, ...)
263 #ifdef MI_COMPILER_GCC
264  __attribute__((format(printf, 4, 5)))
265 #endif
266  {
267  va_list args;
268  va_start( args, message);
269  char buffer[1024];
270 #ifdef MI_COMPILER_MSC
271  vsnprintf_s( &buffer[0], sizeof( buffer), sizeof( buffer)-1, message, args);
272 #else
273  vsnprintf( buffer, sizeof( buffer), message, args);
274 #endif
275  this->message( level, module_category, Message_details(), buffer);
276  va_end( args);
277  }
278 
283  inline void printf(
284  Message_severity level, const char* module_category, const Message_details& details, const char* message, ...)
285 #ifdef MI_COMPILER_GCC
286  __attribute__((format(printf, 5, 6)))
287 #endif
288  {
289  va_list args;
290  va_start( args, message);
291  char buffer[1024];
292 #ifdef MI_COMPILER_MSC
293  vsnprintf_s( buffer, sizeof( buffer), sizeof( buffer)-1, message, args);
294 #else
295  vsnprintf( buffer, sizeof( buffer), message, args);
296 #endif
297  this->message( level, module_category, details, buffer);
298  va_end( args);
299  }
300 };
301 
302 // A specialization of std::stringbuf to be used together with #mi::base::Log_stream.
303 //
304 // Its sync() method is overridden to send the contents of the string buffer to the logger, and an
305 // additional method #set_log_level() allows to specify the log level of the next message.
307 {
308 public:
309  // Constructor.
310  //
311  // \param stream The stream used with this string buffer. Used to flush the stream
312  // if the log level is changed.
313  // \param logger The logger that finally receives the contents of this string
314  // buffer.
315  // \param module_category The module and the category which specify the origin and the
316  // functional area of this message. See #mi::base::ILogger::message()
317  // for details.
318  // \param default_level The default log level. Used if no other log level is selected by
319  // one of the manipulators.
320  // \param default_details The default message details. Used if no other details are set.
322  std::ostream& stream,
323  ILogger* logger,
324  const std::string& module_category,
325  Message_severity default_level = MESSAGE_SEVERITY_INFO,
326  const Message_details& default_details = Message_details())
327  : std::stringbuf( std::ios::out),
328  m_stream( stream),
329  m_default_level( default_level),
330  m_default_details( default_details),
331  m_logger( logger, DUP_INTERFACE),
332  m_module_category( module_category),
333  m_details( default_details)
334  {
335  set_log_level( m_default_level);
336  }
337 
338  // Destructor.
339  ~Log_streambuf() throw()
340  {
341  }
342 
343  // Flushes the string buffer if not empty, and sets the log level of the next message to the
344  // given log level.
345  void set_log_level( Message_severity level)
346  {
347  m_stream.flush();
348  m_level = level;
349  }
350 
351  // Flushes the string buffer if not empty, and sets the log level of the next message to the
352  // given log level.
353  void set_details( const Message_details& details)
354  {
355  m_stream.flush();
356  m_details = details;
357  }
358 
359 protected:
360 
361  // Sends the contents of the string buffer to the logger, clears the string buffer, and resets
362  // the log level and details to their defaults.
363  int sync()
364  {
366  const std::string& s = str();
367  if( !s.empty()) {
368  m_logger->message( m_level, m_module_category.c_str(), m_details, s.c_str());
369  str( "");
370  m_level = m_default_level;
371  m_details = m_default_details;
372  }
373  return 0;
374  }
375 
376 private:
377 
378  std::ostream& m_stream;
379  Message_severity m_default_level;
380  Message_details m_default_details;
381  mi::base::Handle<ILogger> m_logger;
382  std::string m_module_category;
383  Message_severity m_level;
384  Message_details m_details;
385 };
386 
403 class Log_stream : public std::ostream
404 {
405 public:
416  ILogger* logger,
417  const char* module_category,
418  Message_severity default_level = MESSAGE_SEVERITY_INFO,
419  const Message_details& default_details = Message_details())
420  : std::ostream( 0),
421  m_buffer( *this, logger, module_category ? module_category : "APP:MAIN",
422  default_level, default_details)
423  {
424  rdbuf( &m_buffer);
425 #if (__cplusplus >= 201402L)
426  this->pword( get_index()) = this;
427 #endif
428  }
429 
440  ILogger* logger,
441  const std::string& module_category,
442  Message_severity default_level = MESSAGE_SEVERITY_INFO,
443  const Message_details& default_details = Message_details())
444  : std::ostream( 0),
445  m_buffer( *this, logger, module_category, default_level, default_details)
446  {
447  rdbuf( &m_buffer);
448 #if (__cplusplus >= 201402L)
449  this->pword( get_index()) = this;
450 #endif
451  }
452 
456  ~Log_stream() throw()
457  {
458  flush();
459  }
460 
463  void set_log_level( Message_severity level) { m_buffer.set_log_level( level); }
464 
466  void set_details( const Message_details& details) { m_buffer.set_details( details); }
467 
468 #if (__cplusplus >= 201402L)
469  // Returns the unique index into the private storage of std::ios_base.
470  static int get_index()
471  {
472  // Static initialization is guaranteed to be thread-safe with C++11 and later. The method
473  // std::ios_base::xalloc() is guaranteed to be thread-safe with C++14 and later.
474  static int s_index = std::ios_base::xalloc();
475  return s_index;
476  }
477 #endif
478 
479 private:
480  Log_streambuf m_buffer;
481 };
482 
492 template <typename C, typename T>
494 {
495 #if (__cplusplus >= 201402L)
496  if( ostream.pword( Log_stream::get_index()) == &ostream)
497 #endif
498  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_FATAL);
499  return ostream;
500 }
501 
511 template <typename C, typename T>
513 {
514 #if (__cplusplus >= 201402L)
515  if( ostream.pword( Log_stream::get_index()) == &ostream)
516 #endif
517  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_ERROR);
518  return ostream;
519 }
520 
530 template <typename C, typename T>
532 {
533 #if (__cplusplus >= 201402L)
534  if( ostream.pword( Log_stream::get_index()) == &ostream)
535 #endif
536  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_WARNING);
537  return ostream;
538 }
539 
549 template <typename C, typename T>
551 {
552 #if (__cplusplus >= 201402L)
553  if( ostream.pword( Log_stream::get_index()) == &ostream)
554 #endif
555  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_INFO);
556  return ostream;
557 }
558 
568 template <typename C, typename T>
570 {
571 #if (__cplusplus >= 201402L)
572  if( ostream.pword( Log_stream::get_index()) == &ostream)
573 #endif
574  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_VERBOSE);
575  return ostream;
576 }
577 
587 template <typename C, typename T>
589 {
590 #if (__cplusplus >= 201402L)
591  if( ostream.pword( Log_stream::get_index()) == &ostream)
592 #endif
593  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_DEBUG);
594  return ostream;
595 }
596 
605 template <typename C, typename T>
606 std::basic_ostream<C, T>& operator<<( std::basic_ostream<C, T>& ostream, const Message_details& md)
607 {
608 #if (__cplusplus >= 201402L)
609  if( ostream.pword( Log_stream::get_index()) == &ostream)
610 #endif
611  static_cast<Log_stream&>( ostream).set_details( md);
612  return ostream;
613 }
614 
615 
616 namespace msg {
617 
618 using namespace details;
619 typedef Message_tag Tag;
620 typedef Message_details Details;
621 
622 inline Details tag_details(const Uint32 tags)
623 {
624  return Details().tag(tags);
625 }
626 
627 inline Details device_details(
628  const Sint32 device=Details::DEVICE_ID_UNKNOWN_CUDA,
629  const Uint32 tags=TAG_NONE)
630 {
631  return Details().tag(tags).device(device);
632 }
633 
634 }
635  // end group mi_base_ilogger
637 
638 } // namespace base
639 
640 } // namespace mi
641 
642 #endif // MI_BASE_ILOGGER_H