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.

383 lines
11KB

  1. // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
  2. // Distributed under the MIT License (http://opensource.org/licenses/MIT)
  3. #pragma once
  4. // Thread safe logger (except for set_error_handler())
  5. // Has name, log level, vector of std::shared sink pointers and formatter
  6. // Upon each log write the logger:
  7. // 1. Checks if its log level is enough to log the message and if yes:
  8. // 2. Call the underlying sinks to do the job.
  9. // 3. Each sink use its own private copy of a formatter to format the message
  10. // and send to its destination.
  11. //
  12. // The use of private formatter per sink provides the opportunity to cache some
  13. // formatted data, and support for different format per sink.
  14. #include "spdlog/common.h"
  15. #include "spdlog/details/log_msg.h"
  16. #include "spdlog/details/backtracer.h"
  17. #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
  18. #include "spdlog/details/os.h"
  19. #endif
  20. #include <vector>
  21. #ifndef SPDLOG_NO_EXCEPTIONS
  22. #define SPDLOG_LOGGER_CATCH() \
  23. catch (const std::exception &ex) \
  24. { \
  25. err_handler_(ex.what()); \
  26. } \
  27. catch (...) \
  28. { \
  29. err_handler_("Unknown exception in logger"); \
  30. }
  31. #else
  32. #define SPDLOG_LOGGER_CATCH()
  33. #endif
  34. namespace spdlog {
  35. class logger
  36. {
  37. public:
  38. // Empty logger
  39. explicit logger(std::string name)
  40. : name_(std::move(name))
  41. , sinks_()
  42. {}
  43. // Logger with range on sinks
  44. template<typename It>
  45. logger(std::string name, It begin, It end)
  46. : name_(std::move(name))
  47. , sinks_(begin, end)
  48. {}
  49. // Logger with single sink
  50. logger(std::string name, sink_ptr single_sink)
  51. : logger(std::move(name), {std::move(single_sink)})
  52. {}
  53. // Logger with sinks init list
  54. logger(std::string name, sinks_init_list sinks)
  55. : logger(std::move(name), sinks.begin(), sinks.end())
  56. {}
  57. virtual ~logger() = default;
  58. logger(const logger &other);
  59. logger(logger &&other) SPDLOG_NOEXCEPT;
  60. logger &operator=(logger other) SPDLOG_NOEXCEPT;
  61. void swap(spdlog::logger &other) SPDLOG_NOEXCEPT;
  62. template<typename... Args>
  63. void log(source_loc loc, level::level_enum lvl, string_view_t fmt, const Args &... args)
  64. {
  65. auto level_enabled = should_log(lvl);
  66. if (!level_enabled && !tracer_)
  67. {
  68. return;
  69. }
  70. SPDLOG_TRY
  71. {
  72. memory_buf_t buf;
  73. fmt::format_to(buf, fmt, args...);
  74. details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));
  75. if (level_enabled)
  76. {
  77. sink_it_(log_msg);
  78. }
  79. if (tracer_)
  80. {
  81. tracer_.push_back(log_msg);
  82. }
  83. }
  84. SPDLOG_LOGGER_CATCH()
  85. }
  86. template<typename... Args>
  87. void log(level::level_enum lvl, string_view_t fmt, const Args &... args)
  88. {
  89. log(source_loc{}, lvl, fmt, args...);
  90. }
  91. template<typename... Args>
  92. void trace(string_view_t fmt, const Args &... args)
  93. {
  94. log(level::trace, fmt, args...);
  95. }
  96. template<typename... Args>
  97. void debug(string_view_t fmt, const Args &... args)
  98. {
  99. log(level::debug, fmt, args...);
  100. }
  101. template<typename... Args>
  102. void info(string_view_t fmt, const Args &... args)
  103. {
  104. log(level::info, fmt, args...);
  105. }
  106. template<typename... Args>
  107. void warn(string_view_t fmt, const Args &... args)
  108. {
  109. log(level::warn, fmt, args...);
  110. }
  111. template<typename... Args>
  112. void error(string_view_t fmt, const Args &... args)
  113. {
  114. log(level::err, fmt, args...);
  115. }
  116. template<typename... Args>
  117. void critical(string_view_t fmt, const Args &... args)
  118. {
  119. log(level::critical, fmt, args...);
  120. }
  121. template<typename T>
  122. void log(level::level_enum lvl, const T &msg)
  123. {
  124. log(source_loc{}, lvl, msg);
  125. }
  126. // T can be statically converted to string_view
  127. template<class T, typename std::enable_if<std::is_convertible<const T &, spdlog::string_view_t>::value, T>::type * = nullptr>
  128. void log(source_loc loc, level::level_enum lvl, const T &msg)
  129. {
  130. auto level_enabled = should_log(lvl);
  131. if (!level_enabled && !tracer_)
  132. {
  133. return;
  134. }
  135. SPDLOG_TRY
  136. {
  137. details::log_msg log_msg(loc, name_, lvl, msg);
  138. if (level_enabled)
  139. {
  140. sink_it_(log_msg);
  141. }
  142. if (tracer_)
  143. {
  144. tracer_.push_back(log_msg);
  145. }
  146. }
  147. SPDLOG_LOGGER_CATCH()
  148. }
  149. void log(level::level_enum lvl, string_view_t msg)
  150. {
  151. log(source_loc{}, lvl, msg);
  152. }
  153. // T cannot be statically converted to string_view or wstring_view
  154. template<class T, typename std::enable_if<!std::is_convertible<const T &, spdlog::string_view_t>::value &&
  155. !is_convertible_to_wstring_view<const T &>::value,
  156. T>::type * = nullptr>
  157. void log(source_loc loc, level::level_enum lvl, const T &msg)
  158. {
  159. log(loc, lvl, "{}", msg);
  160. }
  161. template<typename T>
  162. void trace(const T &msg)
  163. {
  164. log(level::trace, msg);
  165. }
  166. template<typename T>
  167. void debug(const T &msg)
  168. {
  169. log(level::debug, msg);
  170. }
  171. template<typename T>
  172. void info(const T &msg)
  173. {
  174. log(level::info, msg);
  175. }
  176. template<typename T>
  177. void warn(const T &msg)
  178. {
  179. log(level::warn, msg);
  180. }
  181. template<typename T>
  182. void error(const T &msg)
  183. {
  184. log(level::err, msg);
  185. }
  186. template<typename T>
  187. void critical(const T &msg)
  188. {
  189. log(level::critical, msg);
  190. }
  191. #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
  192. #ifndef _WIN32
  193. #error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows
  194. #else
  195. template<typename... Args>
  196. void log(source_loc loc, level::level_enum lvl, wstring_view_t fmt, const Args &... args)
  197. {
  198. auto level_enabled = should_log(lvl);
  199. if (!level_enabled && !tracer_)
  200. {
  201. return;
  202. }
  203. SPDLOG_TRY
  204. {
  205. // format to wmemory_buffer and convert to utf8
  206. fmt::wmemory_buffer wbuf;
  207. fmt::format_to(wbuf, fmt, args...);
  208. memory_buf_t buf;
  209. details::os::wstr_to_utf8buf(wstring_view_t(wbuf.data(), wbuf.size()), buf);
  210. details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));
  211. if (level_enabled)
  212. {
  213. sink_it_(log_msg);
  214. }
  215. if (tracer_)
  216. {
  217. tracer_.push_back(log_msg);
  218. }
  219. }
  220. SPDLOG_LOGGER_CATCH()
  221. }
  222. template<typename... Args>
  223. void log(level::level_enum lvl, wstring_view_t fmt, const Args &... args)
  224. {
  225. log(source_loc{}, lvl, fmt, args...);
  226. }
  227. template<typename... Args>
  228. void trace(wstring_view_t fmt, const Args &... args)
  229. {
  230. log(level::trace, fmt, args...);
  231. }
  232. template<typename... Args>
  233. void debug(wstring_view_t fmt, const Args &... args)
  234. {
  235. log(level::debug, fmt, args...);
  236. }
  237. template<typename... Args>
  238. void info(wstring_view_t fmt, const Args &... args)
  239. {
  240. log(level::info, fmt, args...);
  241. }
  242. template<typename... Args>
  243. void warn(wstring_view_t fmt, const Args &... args)
  244. {
  245. log(level::warn, fmt, args...);
  246. }
  247. template<typename... Args>
  248. void error(wstring_view_t fmt, const Args &... args)
  249. {
  250. log(level::err, fmt, args...);
  251. }
  252. template<typename... Args>
  253. void critical(wstring_view_t fmt, const Args &... args)
  254. {
  255. log(level::critical, fmt, args...);
  256. }
  257. // T can be statically converted to wstring_view
  258. template<class T, typename std::enable_if<is_convertible_to_wstring_view<const T &>::value, T>::type * = nullptr>
  259. void log(source_loc loc, level::level_enum lvl, const T &msg)
  260. {
  261. if (!should_log(lvl))
  262. {
  263. return;
  264. }
  265. try
  266. {
  267. memory_buf_t buf;
  268. details::os::wstr_to_utf8buf(msg, buf);
  269. details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));
  270. sink_it_(log_msg);
  271. }
  272. SPDLOG_LOGGER_CATCH()
  273. }
  274. #endif // _WIN32
  275. #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
  276. bool should_log(level::level_enum msg_level) const;
  277. void set_level(level::level_enum log_level);
  278. level::level_enum level() const;
  279. const std::string &name() const;
  280. // set formatting for the sinks in this logger.
  281. // each sink will get a seperate instance of the formatter object.
  282. void set_formatter(std::unique_ptr<formatter> f);
  283. void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local);
  284. // backtrace support.
  285. // efficiently store all debug/trace messages in a circular buffer until needed for debugging.
  286. void enable_backtrace(size_t n_messages);
  287. void disable_backtrace();
  288. void dump_backtrace();
  289. // flush functions
  290. void flush();
  291. void flush_on(level::level_enum log_level);
  292. level::level_enum flush_level() const;
  293. // sinks
  294. const std::vector<sink_ptr> &sinks() const;
  295. std::vector<sink_ptr> &sinks();
  296. // error handler
  297. void set_error_handler(err_handler);
  298. // create new logger with same sinks and configuration.
  299. virtual std::shared_ptr<logger> clone(std::string logger_name);
  300. protected:
  301. std::string name_;
  302. std::vector<sink_ptr> sinks_;
  303. spdlog::level_t level_{level::info};
  304. spdlog::level_t flush_level_{level::off};
  305. err_handler custom_err_handler_{nullptr};
  306. details::backtracer tracer_;
  307. virtual void sink_it_(const details::log_msg &msg);
  308. virtual void flush_();
  309. void dump_backtrace_();
  310. bool should_flush_(const details::log_msg &msg);
  311. // handle errors during logging.
  312. // default handler prints the error to stderr at max rate of 1 message/sec.
  313. void err_handler_(const std::string &msg);
  314. };
  315. void swap(logger &a, logger &b);
  316. } // namespace spdlog
  317. #ifdef SPDLOG_HEADER_ONLY
  318. #include "logger-inl.h"
  319. #endif