Logger.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright (C) 2009-2021, 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. NORMAL,
  19. VERBOSE,
  20. ERROR,
  21. WARNING,
  22. FATAL,
  23. COUNT
  24. };
  25. /// Used as parammeter when emitting the signal.
  26. /// @memberof Logger
  27. class LoggerMessageInfo
  28. {
  29. public:
  30. const char* m_file;
  31. I32 m_line;
  32. const char* m_func;
  33. LoggerMessageType m_type;
  34. const char* m_msg;
  35. const char* m_subsystem;
  36. ThreadId m_tid;
  37. };
  38. /// The message handler callback.
  39. /// @memberof Logger
  40. using LoggerMessageHandlerCallback = void (*)(void*, const LoggerMessageInfo& info);
  41. /// The logger singleton class. The logger cannot print errors or throw exceptions, it has to recover somehow. It's
  42. /// thread safe.
  43. /// To add a new signal:
  44. /// @code logger.addMessageHandler((void*)obj, &function) @endcode
  45. class Logger
  46. {
  47. public:
  48. /// Initialize the logger and add the default message handler
  49. Logger();
  50. ~Logger();
  51. /// Add a new message handler.
  52. void addMessageHandler(void* data, LoggerMessageHandlerCallback callback);
  53. /// Remove a message handler.
  54. void removeMessageHandler(void* data, LoggerMessageHandlerCallback callback);
  55. /// Add file message handler.
  56. void addFileMessageHandler(File* file);
  57. /// Send a message.
  58. void write(const char* file, int line, const char* func, const char* subsystem, LoggerMessageType type,
  59. ThreadId tid, const char* msg);
  60. /// Send a formated message.
  61. ANKI_CHECK_FORMAT(7, 8)
  62. void writeFormated(const char* file, int line, const char* func, const char* subsystem, LoggerMessageType type,
  63. ThreadId tid, const char* fmt, ...);
  64. /// Enable or disable logger verbosity.
  65. void enableVerbosity(Bool enable)
  66. {
  67. m_verbosityEnabled = enable;
  68. }
  69. private:
  70. class Handler
  71. {
  72. public:
  73. void* m_data = nullptr;
  74. LoggerMessageHandlerCallback m_callback = nullptr;
  75. Handler() = default;
  76. Handler(const Handler&) = default;
  77. Handler(void* data, LoggerMessageHandlerCallback callback)
  78. : m_data(data)
  79. , m_callback(callback)
  80. {
  81. }
  82. };
  83. Mutex m_mutex; ///< For thread safety
  84. Array<Handler, 4> m_handlers;
  85. U32 m_handlersCount = 0;
  86. Bool m_verbosityEnabled = false;
  87. static void defaultSystemMessageHandler(void*, const LoggerMessageInfo& info);
  88. static void fileMessageHandler(void* file, const LoggerMessageInfo& info);
  89. };
  90. using LoggerSingleton = Singleton<Logger>;
  91. #define ANKI_LOG(subsystem_, t, ...) \
  92. do \
  93. { \
  94. LoggerSingleton::get().writeFormated(ANKI_FILE, __LINE__, ANKI_FUNC, subsystem_, LoggerMessageType::t, \
  95. Thread::getCurrentThreadId(), __VA_ARGS__); \
  96. } while(false);
  97. /// @}
  98. /// @addtogroup util_logging
  99. /// @{
  100. /// Log information message.
  101. #define ANKI_LOGI(...) ANKI_LOG(nullptr, NORMAL, __VA_ARGS__)
  102. /// Log verbose information message.
  103. #define ANKI_LOGV(...) ANKI_LOG(nullptr, VERBOSE, __VA_ARGS__)
  104. /// Log warning message.
  105. #define ANKI_LOGW(...) ANKI_LOG(nullptr, WARNING, __VA_ARGS__)
  106. /// Log error message.
  107. #define ANKI_LOGE(...) ANKI_LOG(nullptr, ERROR, __VA_ARGS__)
  108. /// Log fatal message. It will will abort.
  109. #define ANKI_LOGF(...) ANKI_LOG(nullptr, FATAL, __VA_ARGS__)
  110. /// @}
  111. } // end namespace anki