logger.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /**
  2. @file
  3. @author Stefan Frings
  4. */
  5. #ifndef LOGGER_H
  6. #define LOGGER_H
  7. #include <QtGlobal>
  8. #include <QThreadStorage>
  9. #include <QHash>
  10. #include <QStringList>
  11. #include <QMutex>
  12. #include <QObject>
  13. #include "logglobal.h"
  14. #include "logmessage.h"
  15. namespace stefanfrings {
  16. /**
  17. Decorates and writes log messages to the console, stderr.
  18. <p>
  19. The decorator uses a predefined msgFormat string to enrich log messages
  20. with additional information (e.g. timestamp).
  21. <p>
  22. The msgFormat string and also the message text may contain additional
  23. variable names in the form <i>{name}</i> that are filled by values
  24. taken from a static thread local dictionary.
  25. <p>
  26. The logger can collect a configurable number of messages in thread-local
  27. FIFO buffers. A log message with severity >= minLevel flushes the buffer,
  28. so the messages are written out. There is one exception:
  29. INFO messages are treated like DEBUG messages (level 0).
  30. <p>
  31. Example: If you enable the buffer and use minLevel=2, then the application
  32. waits until an error occurs. Then it writes out the error message together
  33. with all buffered lower level messages of the same thread. But as long no
  34. error occurs, nothing gets written out.
  35. <p>
  36. If the buffer is disabled, then only messages with severity >= minLevel
  37. are written out.
  38. <p>
  39. The logger can be registered to handle messages from
  40. the static global functions qDebug(), qWarning(), qCritical(), qFatal() and qInfo().
  41. @see set() describes how to set logger variables
  42. @see LogMessage for a description of the message decoration.
  43. @warning You should prefer a derived class, for example FileLogger,
  44. because logging to the console is less useful.
  45. */
  46. class DECLSPEC Logger : public QObject {
  47. Q_OBJECT
  48. Q_DISABLE_COPY(Logger)
  49. public:
  50. /**
  51. Constructor.
  52. Uses the same defaults as the other constructor.
  53. @param parent Parent object
  54. */
  55. Logger(QObject* parent);
  56. /**
  57. Constructor.
  58. Possible log levels are: 0=DEBUG, 1=WARNING, 2=CRITICAL, 3=FATAL, 4=INFO
  59. @param msgFormat Format of the decoration, e.g. "{timestamp} {type} thread={thread}: {msg}"
  60. @param timestampFormat Format of timestamp, e.g. "dd.MM.yyyy hh:mm:ss.zzz"
  61. @param minLevel If bufferSize=0: Messages with lower level discarded.<br>
  62. If buffersize>0: Messages with lower level are buffered, messages with equal or higher level trigger writing the buffered content.
  63. @param bufferSize Size of the backtrace buffer, number of messages per thread. 0=disabled.
  64. @param parent Parent object
  65. @see LogMessage for a description of the message decoration.
  66. */
  67. Logger(const QString msgFormat="{timestamp} {type} {msg}",
  68. const QString timestampFormat="dd.MM.yyyy hh:mm:ss.zzz",
  69. const QtMsgType minLevel=QtDebugMsg, const int bufferSize=0,
  70. QObject* parent = nullptr);
  71. /** Destructor */
  72. virtual ~Logger();
  73. /**
  74. Decorate and log the message, if type>=minLevel.
  75. This method is thread safe.
  76. @param type Message type (level)
  77. @param message Message text
  78. @param file Name of the source file where the message was generated (usually filled with the macro __FILE__)
  79. @param function Name of the function where the message was generated (usually filled with the macro __LINE__)
  80. @param line Line Number of the source file, where the message was generated (usually filles with the macro __func__ or __FUNCTION__)
  81. @see LogMessage for a description of the message decoration.
  82. */
  83. virtual void log(const QtMsgType type, const QString& message, const QString &file="",
  84. const QString &function="", const int line=0);
  85. /**
  86. Installs this logger as the default message handler, so it
  87. can be used through the global static logging functions (e.g. qDebug()).
  88. */
  89. void installMsgHandler();
  90. /**
  91. Sets a thread-local variable that may be used to decorate log messages.
  92. This method is thread safe.
  93. @param name Name of the variable
  94. @param value Value of the variable
  95. */
  96. static void set(const QString& name, const QString& value);
  97. /**
  98. Clear the thread-local data of the current thread.
  99. This method is thread safe.
  100. @param buffer Whether to clear the backtrace buffer
  101. @param variables Whether to clear the log variables
  102. */
  103. virtual void clear(const bool buffer=true, const bool variables=true);
  104. protected:
  105. /** Format string for message decoration */
  106. QString msgFormat;
  107. /** Format string of timestamps */
  108. QString timestampFormat;
  109. /** Minimum level of message types that are written out directly or trigger writing the buffered content. */
  110. QtMsgType minLevel;
  111. /** Size of backtrace buffer, number of messages per thread. 0=disabled */
  112. int bufferSize;
  113. /** Used to synchronize access of concurrent threads */
  114. static QMutex mutex;
  115. /**
  116. Decorate and write a log message to stderr. Override this method
  117. to provide a different output medium.
  118. */
  119. virtual void write(const LogMessage* logMessage);
  120. private:
  121. /** Pointer to the default logger, used by msgHandler() */
  122. static Logger* defaultLogger;
  123. /**
  124. Message Handler for the global static logging functions (e.g. qDebug()).
  125. Forward calls to the default logger.
  126. <p>
  127. In case of a fatal message, the program will abort.
  128. Variables in the in the message are replaced by their values.
  129. This method is thread safe.
  130. @param type Message type (level)
  131. @param message Message text
  132. @param file Name of the source file where the message was generated (usually filled with the macro __FILE__)
  133. @param function Name of the function where the message was generated (usually filled with the macro __LINE__)
  134. @param line Line Number of the source file, where the message was generated (usually filles with the macro __func__ or __FUNCTION__)
  135. */
  136. static void msgHandler(const QtMsgType type, const QString &message, const QString &file="",
  137. const QString &function="", const int line=0);
  138. #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
  139. /**
  140. Wrapper for QT version 5.
  141. @param type Message type (level)
  142. @param context Message context
  143. @param message Message text
  144. @see msgHandler()
  145. */
  146. static void msgHandler5(const QtMsgType type, const QMessageLogContext& context, const QString &message);
  147. #else
  148. /**
  149. Wrapper for QT version 4.
  150. @param type Message type (level)
  151. @param message Message text
  152. @see msgHandler()
  153. */
  154. static void msgHandler4(const QtMsgType type, const char * message);
  155. #endif
  156. /** Thread local variables to be used in log messages */
  157. static QThreadStorage<QHash<QString,QString>*> logVars;
  158. /** Thread local backtrace buffers */
  159. QThreadStorage<QList<LogMessage*>*> buffers;
  160. };
  161. } // end of namespace
  162. #endif // LOGGER_H