Logger.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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. {
  11. // Forward
  12. class File;
  13. /// @addtogroup util_other
  14. /// @{
  15. /// Logger message type.
  16. /// @memberof Logger
  17. enum class LoggerMessageType : U8
  18. {
  19. NORMAL,
  20. VERBOSE,
  21. ERROR,
  22. WARNING,
  23. FATAL,
  24. COUNT
  25. };
  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. ThreadId m_tid;
  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
  43. /// thread safe.
  44. /// To add a new signal:
  45. /// @code logger.addMessageHandler((void*)obj, &function) @endcode
  46. class Logger
  47. {
  48. public:
  49. /// Initialize the logger and add the default message handler
  50. Logger();
  51. ~Logger();
  52. /// Add a new message handler.
  53. void addMessageHandler(void* data, LoggerMessageHandlerCallback callback);
  54. /// Remove a message handler.
  55. void removeMessageHandler(void* data, LoggerMessageHandlerCallback callback);
  56. /// Add file message handler.
  57. void addFileMessageHandler(File* file);
  58. /// Send a message.
  59. void write(const char* file, int line, const char* func, const char* subsystem, LoggerMessageType type,
  60. ThreadId tid, const char* msg);
  61. /// Send a formated message.
  62. ANKI_CHECK_FORMAT(7, 8)
  63. void writeFormated(const char* file, int line, const char* func, const char* subsystem, LoggerMessageType type,
  64. ThreadId tid, const char* fmt, ...);
  65. /// Enable or disable logger verbosity.
  66. void enableVerbosity(Bool enable)
  67. {
  68. m_verbosityEnabled = enable;
  69. }
  70. private:
  71. class Handler
  72. {
  73. public:
  74. void* m_data = nullptr;
  75. LoggerMessageHandlerCallback m_callback = nullptr;
  76. Handler() = default;
  77. Handler(const Handler&) = default;
  78. Handler(void* data, LoggerMessageHandlerCallback callback)
  79. : m_data(data)
  80. , m_callback(callback)
  81. {
  82. }
  83. };
  84. Mutex m_mutex; ///< For thread safety
  85. Array<Handler, 4> m_handlers;
  86. U32 m_handlersCount = 0;
  87. Bool m_verbosityEnabled = false;
  88. static void defaultSystemMessageHandler(void*, const LoggerMessageInfo& info);
  89. static void fileMessageHandler(void* file, const LoggerMessageInfo& info);
  90. };
  91. using LoggerSingleton = Singleton<Logger>;
  92. #define ANKI_LOG(subsystem_, t, ...) \
  93. do \
  94. { \
  95. LoggerSingleton::get().writeFormated(ANKI_FILE, __LINE__, ANKI_FUNC, subsystem_, LoggerMessageType::t, \
  96. Thread::getCurrentThreadId(), __VA_ARGS__); \
  97. } while(false);
  98. /// @}
  99. /// @addtogroup util_logging
  100. /// @{
  101. /// Log information message.
  102. #define ANKI_LOGI(...) ANKI_LOG(nullptr, NORMAL, __VA_ARGS__)
  103. /// Log verbose information message.
  104. #define ANKI_LOGV(...) ANKI_LOG(nullptr, VERBOSE, __VA_ARGS__)
  105. /// Log warning message.
  106. #define ANKI_LOGW(...) ANKI_LOG(nullptr, WARNING, __VA_ARGS__)
  107. /// Log error message.
  108. #define ANKI_LOGE(...) ANKI_LOG(nullptr, ERROR, __VA_ARGS__)
  109. /// Log fatal message. It will will abort.
  110. #define ANKI_LOGF(...) ANKI_LOG(nullptr, FATAL, __VA_ARGS__)
  111. /// @}
  112. } // end namespace anki