Logger.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Config.h>
  7. #include <AnKi/Util/Singleton.h>
  8. #include <AnKi/Util/Thread.h>
  9. namespace anki {
  10. // Forward
  11. class File;
  12. /// @addtogroup util_other
  13. /// @{
  14. /// Logger message type.
  15. /// @memberof Logger
  16. enum class LoggerMessageType : U8
  17. {
  18. kNormal,
  19. kVerbose,
  20. kError,
  21. kWarning,
  22. kFatal,
  23. kCount
  24. };
  25. inline constexpr Array<const Char*, U(LoggerMessageType::kCount)> kLoggerMessageTypeText = {"I", "V", "E", "W", "F"};
  26. /// Used as parammeter when emitting the signal.
  27. /// @memberof Logger
  28. class LoggerMessageInfo
  29. {
  30. public:
  31. const Char* m_file;
  32. I32 m_line;
  33. const Char* m_func;
  34. LoggerMessageType m_type;
  35. const Char* m_msg;
  36. const Char* m_subsystem;
  37. const Char* m_threadName;
  38. };
  39. /// The message handler callback.
  40. /// @memberof Logger
  41. using LoggerMessageHandlerCallback = void (*)(void*, const LoggerMessageInfo& info);
  42. /// The logger singleton class. The logger cannot print errors or throw exceptions, it has to recover somehow. It's thread safe.
  43. /// To add a new signal:
  44. /// @code logger.addMessageHandler((void*)obj, &function) @endcode
  45. class Logger : public MakeSingleton<Logger>
  46. {
  47. template<typename>
  48. friend class MakeSingleton;
  49. public:
  50. /// Add a new message handler.
  51. void addMessageHandler(void* data, LoggerMessageHandlerCallback callback);
  52. /// Remove a message handler.
  53. void removeMessageHandler(void* data, LoggerMessageHandlerCallback callback);
  54. /// Add file message handler.
  55. void addFileMessageHandler(File* file);
  56. /// Send a message.
  57. void write(const Char* file, int line, const Char* func, const Char* subsystem, LoggerMessageType type, const Char* threadName, const Char* msg)
  58. {
  59. // Note: m_verbosityEnabled is not accessed in a thread-safe way. It doesn't really matter though
  60. if(type == LoggerMessageType::kVerbose && !m_verbosityEnabled)
  61. {
  62. return;
  63. }
  64. writeInternal(file, line, func, subsystem, type, threadName, msg);
  65. }
  66. /// Send a formated message.
  67. ANKI_CHECK_FORMAT(7, 8)
  68. void writeFormated(const Char* file, int line, const Char* func, const Char* subsystem, LoggerMessageType type, const Char* threadName,
  69. const Char* fmt, ...);
  70. /// Enable or disable logger verbosity.
  71. void enableVerbosity(Bool enable)
  72. {
  73. m_verbosityEnabled = enable;
  74. }
  75. Bool verbosityEnabled() const
  76. {
  77. return m_verbosityEnabled;
  78. }
  79. private:
  80. class Handler
  81. {
  82. public:
  83. void* m_data = nullptr;
  84. LoggerMessageHandlerCallback m_callback = nullptr;
  85. };
  86. Mutex m_mutex; ///< For thread safety
  87. Array<Handler, 4> m_handlers;
  88. U32 m_handlersCount = 0;
  89. Bool m_verbosityEnabled = false;
  90. /// Initialize the logger and add the default message handler
  91. Logger();
  92. ~Logger();
  93. static void defaultSystemMessageHandler(void*, const LoggerMessageInfo& info);
  94. static void fileMessageHandler(void* file, const LoggerMessageInfo& info);
  95. void writeInternal(const Char* file, int line, const Char* func, const Char* subsystem, LoggerMessageType type, const Char* threadName,
  96. const Char* msg);
  97. };
  98. #define ANKI_LOG(subsystem_, t, ...) \
  99. do \
  100. { \
  101. Logger::getSingleton().writeFormated(ANKI_FILE, __LINE__, ANKI_FUNC, subsystem_, LoggerMessageType::t, Thread::getCurrentThreadName(), \
  102. __VA_ARGS__); \
  103. } while(false)
  104. /// @}
  105. /// @addtogroup util_logging
  106. /// @{
  107. /// Log information message.
  108. #define ANKI_LOGI(...) ANKI_LOG(nullptr, kNormal, __VA_ARGS__)
  109. /// Log verbose information message.
  110. #define ANKI_LOGV(...) ANKI_LOG(nullptr, kVerbose, __VA_ARGS__)
  111. /// Log warning message.
  112. #define ANKI_LOGW(...) ANKI_LOG(nullptr, kWarning, __VA_ARGS__)
  113. /// Log error message.
  114. #define ANKI_LOGE(...) ANKI_LOG(nullptr, kError, __VA_ARGS__)
  115. /// Log fatal message. It will will abort.
  116. #define ANKI_LOGF(...) ANKI_LOG(nullptr, kFatal, __VA_ARGS__)
  117. /// @}
  118. } // end namespace anki