💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
5.9 KiB

  1. /*
  2. * Copyright (C) 2023 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_DEBUG_LOG_HPP
  20. #define ANTKEEPER_DEBUG_LOG_HPP
  21. #include "config.hpp"
  22. #include "debug/log/message-severity.hpp"
  23. #include "debug/log/logger.hpp"
  24. #include <source_location>
  25. #include <string>
  26. #include <format>
  27. // Enable logging of messages of all severities by default.
  28. #if !defined(ANTKEEPER_DEBUG_LOG_MIN_MESSAGE_SEVERITY)
  29. #define ANTKEEPER_DEBUG_LOG_MIN_MESSAGE_SEVERITY (ANTKEEPER_DEBUG_LOG_MESSAGE_SEVERITY_TRACE)
  30. #endif
  31. namespace debug {
  32. /**
  33. * Debug message logging.
  34. */
  35. namespace log {
  36. /**
  37. * Returns the default logger.
  38. */
  39. [[nodiscard]] logger& default_logger() noexcept;
  40. /**
  41. * Self-formatting message that logs itself to the default logger on construction.
  42. *
  43. * @tparam Severity Message severity. A message will not log itself if @p Severity is less than the user-defined macro `ANTKEEPER_DEBUG_LOG_MIN_MESSAGE_SEVERITY`.
  44. * @tparam Args Types of arguments to be formatted.
  45. */
  46. template <message_severity Severity, class... Args>
  47. struct message
  48. {
  49. /**
  50. * Formats and logs a message.
  51. *
  52. * Class template argument deduction (CTAD) is utilized to capture source location as a default argument following variadic format arguments.
  53. *
  54. * @param format Message format string.
  55. * @param args Arguments to be formatted.
  56. * @param location Source location from which the message was sent.
  57. */
  58. message
  59. (
  60. [[maybe_unused]] std::string_view format,
  61. [[maybe_unused]] Args&&... args,
  62. [[maybe_unused]] std::source_location&& location = std::source_location::current()
  63. )
  64. {
  65. if constexpr (ANTKEEPER_DEBUG_LOG_MIN_MESSAGE_SEVERITY <= static_cast<std::underlying_type_t<message_severity>>(Severity))
  66. {
  67. default_logger().log(std::vformat(format, std::make_format_args(std::forward<Args>(args)...)), Severity, std::forward<std::source_location>(location));
  68. }
  69. }
  70. };
  71. // Use class template argument deduction (CTAD) to capture source location as a default argument following variadic format arguments.
  72. template <message_severity Severity, class... Args>
  73. message(std::string_view, Args&&...) -> message<Severity, Args...>;
  74. #if (ANTKEEPER_DEBUG_LOG_MIN_MESSAGE_SEVERITY <= ANTKEEPER_DEBUG_LOG_MESSAGE_SEVERITY_TRACE)
  75. /**
  76. * Formats and logs a trace message.
  77. *
  78. * @tparam Args Types of arguments to be formatted.
  79. */
  80. template <class... Args>
  81. using trace = message<message_severity::trace, Args...>;
  82. #else
  83. // Disable trace message logging.
  84. inline void trace([[maybe_unused]] ...) noexcept {};
  85. #endif
  86. #if (ANTKEEPER_DEBUG_LOG_MIN_MESSAGE_SEVERITY <= ANTKEEPER_DEBUG_LOG_MESSAGE_SEVERITY_DEBUG)
  87. /**
  88. * Formats and logs a debug message.
  89. *
  90. * @tparam Args Types of arguments to be formatted.
  91. */
  92. template <class... Args>
  93. using debug = message<message_severity::debug, Args...>;
  94. #else
  95. // Disable debug message logging.
  96. inline void debug([[maybe_unused]] ...) noexcept {};
  97. #endif
  98. #if (ANTKEEPER_DEBUG_LOG_MIN_MESSAGE_SEVERITY <= ANTKEEPER_DEBUG_LOG_MESSAGE_SEVERITY_INFO)
  99. /**
  100. * Formats and logs an info message.
  101. *
  102. * @tparam Args Types of arguments to be formatted.
  103. */
  104. template <class... Args>
  105. using info = message<message_severity::info, Args...>;
  106. #else
  107. // Disable info message logging.
  108. inline void info([[maybe_unused]] ...) noexcept {};
  109. #endif
  110. #if (ANTKEEPER_DEBUG_LOG_MIN_MESSAGE_SEVERITY <= ANTKEEPER_DEBUG_LOG_MESSAGE_SEVERITY_WARNING)
  111. /**
  112. * Formats and logs a warning message.
  113. *
  114. * @tparam Args Types of arguments to be formatted.
  115. */
  116. template <class... Args>
  117. using warning = message<message_severity::warning, Args...>;
  118. #else
  119. // Disable warning message logging.
  120. inline void warning([[maybe_unused]] ...) noexcept {};
  121. #endif
  122. #if (ANTKEEPER_DEBUG_LOG_MIN_MESSAGE_SEVERITY <= ANTKEEPER_DEBUG_LOG_MESSAGE_SEVERITY_ERROR)
  123. /**
  124. * Formats and logs an error message.
  125. *
  126. * @tparam Args Types of arguments to be formatted.
  127. */
  128. template <class... Args>
  129. using error = message<message_severity::error, Args...>;
  130. #else
  131. // Disable error message logging.
  132. inline void error([[maybe_unused]] ...) noexcept {};
  133. #endif
  134. #if (ANTKEEPER_DEBUG_LOG_MIN_MESSAGE_SEVERITY <= ANTKEEPER_DEBUG_LOG_MESSAGE_SEVERITY_FATAL)
  135. /**
  136. * Formats and logs a fatal error message.
  137. *
  138. * @tparam Args Types of arguments to be formatted.
  139. */
  140. template <class... Args>
  141. using fatal = message<message_severity::fatal, Args...>;
  142. #else
  143. // Disable fatal error message logging.
  144. inline void fatal([[maybe_unused]] ...) noexcept {};
  145. #endif
  146. /**
  147. * Pushes a task onto the default logger's task stack and writes its description the log.
  148. *
  149. * @param description Task description.
  150. * @param location Source location from which the message was sent.
  151. */
  152. void push_task
  153. (
  154. const std::string& description,
  155. std::source_location&& location = std::source_location::current()
  156. );
  157. /**
  158. * Pops a task off the default logger's task stack and writes its status to the log.
  159. *
  160. * @param status Exit status of the task. A value of `0` or `EXIT_SUCCESS` indicates the task exited successfully. A non-zero exit status indicates the task failed.
  161. * @param description Error code description.
  162. */
  163. void pop_task
  164. (
  165. int status,
  166. const std::string& description = std::string(),
  167. std::source_location&& location = std::source_location::current()
  168. );
  169. } // namespace log
  170. } // namespace debug
  171. #endif // ANTKEEPER_DEBUG_LOG_HPP