logger.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Logger front-end
  2. //
  3. // Platform: ISO C++ 98/11/17/20
  4. // $Id$
  5. //
  6. // (c) __vic 2011
  7. #ifndef __VIC_LOGGER_H
  8. #define __VIC_LOGGER_H
  9. #include<__vic/defs.h>
  10. #include<__vic/string_buffer.h>
  11. #if __has_include(<string_view>)
  12. #include<string_view>
  13. #endif
  14. #if __has_include(<format>)
  15. #include<format>
  16. #endif
  17. namespace __vic {
  18. //////////////////////////////////////////////////////////////////////////////
  19. class logger : private non_copyable
  20. {
  21. public:
  22. __VIC_SCOPED_ENUM_UT_BEGIN(severity, unsigned char)
  23. {
  24. trace,
  25. debug,
  26. info, // Default severity
  27. notice, // Normal but significant event
  28. warning, // Insignificant error
  29. error, // Severe error. Application can continue running
  30. fatal // Critical unrecoverable error. Application can't
  31. // continue running
  32. }
  33. __VIC_SCOPED_ENUM_END(severity)
  34. struct output
  35. {
  36. virtual void publish_record(severity_t , const char * , size_t ) = 0;
  37. protected:
  38. ~output() __VIC_DEFAULT_CTR
  39. };
  40. struct settings_t
  41. {
  42. struct output *out;
  43. severity_t lvl;
  44. struct output &output() const { return *out; }
  45. severity_t level() const { return lvl; }
  46. };
  47. class record;
  48. explicit logger(output & , severity_t = severity::info);
  49. explicit logger(settings_t );
  50. ~logger();
  51. severity_t level() const { return log_level; }
  52. void level(severity_t new_level) { log_level = new_level; }
  53. settings_t settings() const { settings_t s = {out, level()}; return s; }
  54. output &reset_output(output &out)
  55. {
  56. output &old = *this->out;
  57. this->out = &out;
  58. return old;
  59. }
  60. output &get_output() { return *out; }
  61. const output &get_output() const { return *out; }
  62. static __VIC_CONSTEXPR_VAR size_t min_buffer_size = 256;
  63. void shrink_buffer(size_t limit)
  64. {
  65. // assert(cur_msg.empty());
  66. if(cur_msg.capacity() > limit)
  67. string_buffer(min_buffer_size).swap(cur_msg);
  68. }
  69. void message(severity_t , const char * , size_t );
  70. #if __cpp_lib_string_view
  71. void message(severity_t s, std::string_view msg)
  72. { message(s, msg.data(), msg.length()); }
  73. void trace(std::string_view msg) { message(severity::trace, msg); }
  74. void debug(std::string_view msg) { message(severity::debug, msg); }
  75. void info(std::string_view msg) { message(severity::info, msg); }
  76. void notice(std::string_view msg) { message(severity::notice, msg); }
  77. void warning(std::string_view msg) { message(severity::warning, msg); }
  78. void error(std::string_view msg) { message(severity::error, msg); }
  79. void fatal(std::string_view msg) { message(severity::fatal, msg); }
  80. #else
  81. void message(severity_t , const char * );
  82. void message(severity_t s, const std::string &msg)
  83. { message(s, msg.data(), msg.length()); }
  84. void trace(const char *msg) { message(severity::trace, msg); }
  85. void debug(const char *msg) { message(severity::debug, msg); }
  86. void info(const char *msg) { message(severity::info, msg); }
  87. void notice(const char *msg) { message(severity::notice, msg); }
  88. void warning(const char *msg) { message(severity::warning, msg); }
  89. void error(const char *msg) { message(severity::error, msg); }
  90. void fatal(const char *msg) { message(severity::fatal, msg); }
  91. void trace(const std::string &msg) { message(severity::trace, msg); }
  92. void debug(const std::string &msg) { message(severity::debug, msg); }
  93. void info(const std::string &msg) { message(severity::info, msg); }
  94. void notice(const std::string &msg) { message(severity::notice, msg); }
  95. void warning(const std::string &msg) { message(severity::warning, msg); }
  96. void error(const std::string &msg) { message(severity::error, msg); }
  97. void fatal(const std::string &msg) { message(severity::fatal, msg); }
  98. #endif
  99. record trace();
  100. record debug();
  101. record info();
  102. record notice();
  103. record warning();
  104. record error();
  105. record fatal();
  106. #if __cpp_lib_format >= 202106L // C++20 + P2508
  107. private:
  108. void vformat_(severity_t , std::string_view , std::format_args );
  109. public:
  110. template<class... Args>
  111. void format(severity_t s, std::format_string<Args...> fmt, Args&&... args)
  112. {
  113. if(s >= level())
  114. vformat_(s, fmt.get(), std::make_format_args(args...));
  115. }
  116. template<class Arg1, class... Args>
  117. void trace(
  118. std::format_string<Arg1,Args...> fmt, Arg1 &&arg1, Args&&... args)
  119. {
  120. format(severity::trace, fmt,
  121. std::forward<Arg1>(arg1), std::forward<Args>(args)...);
  122. }
  123. template<class Arg1, class... Args>
  124. void debug(
  125. std::format_string<Arg1,Args...> fmt, Arg1 &&arg1, Args&&... args)
  126. {
  127. format(severity::debug, fmt,
  128. std::forward<Arg1>(arg1), std::forward<Args>(args)...);
  129. }
  130. template<class Arg1, class... Args>
  131. void info(
  132. std::format_string<Arg1,Args...> fmt, Arg1 &&arg1, Args&&... args)
  133. {
  134. format(severity::info, fmt,
  135. std::forward<Arg1>(arg1), std::forward<Args>(args)...);
  136. }
  137. template<class Arg1, class... Args>
  138. void notice(
  139. std::format_string<Arg1,Args...> fmt, Arg1 &&arg1, Args&&... args)
  140. {
  141. format(severity::notice, fmt,
  142. std::forward<Arg1>(arg1), std::forward<Args>(args)...);
  143. }
  144. template<class Arg1, class... Args>
  145. void warning(
  146. std::format_string<Arg1,Args...> fmt, Arg1 &&arg1, Args&&... args)
  147. {
  148. format(severity::warning, fmt,
  149. std::forward<Arg1>(arg1), std::forward<Args>(args)...);
  150. }
  151. template<class Arg1, class... Args>
  152. void error(
  153. std::format_string<Arg1,Args...> fmt, Arg1 &&arg1, Args&&... args)
  154. {
  155. format(severity::error, fmt,
  156. std::forward<Arg1>(arg1), std::forward<Args>(args)...);
  157. }
  158. template<class Arg1, class... Args>
  159. void fatal(
  160. std::format_string<Arg1,Args...> fmt, Arg1 &&arg1, Args&&... args)
  161. {
  162. format(severity::fatal, fmt,
  163. std::forward<Arg1>(arg1), std::forward<Args>(args)...);
  164. }
  165. #endif
  166. bool trace_visible() const { return level() <= severity::trace; }
  167. bool debug_visible() const { return level() <= severity::debug; }
  168. bool info_visible() const { return level() <= severity::info; }
  169. bool notice_visible() const { return level() <= severity::notice; }
  170. bool warning_visible() const { return level() <= severity::warning; }
  171. bool error_visible() const { return level() <= severity::error; }
  172. bool fatal_visible() const { return level() <= severity::fatal; }
  173. private:
  174. output *out;
  175. //severity log_level; // moved to make the struct more compact
  176. // current record buffer
  177. string_buffer cur_msg;
  178. size_t rec_objs_count;
  179. severity_t cur_severity;
  180. severity_t log_level;
  181. void flush_();
  182. void inc_count_() { rec_objs_count++; }
  183. void dec_count_() { if(--rec_objs_count == 0) flush_(); }
  184. };
  185. //////////////////////////////////////////////////////////////////////////////
  186. class logger::record
  187. {
  188. logger &log;
  189. public:
  190. record(logger &log, severity_t severity) : log(log)
  191. {
  192. log.cur_severity = severity;
  193. log.inc_count_();
  194. }
  195. record(const record &o) : log(o.log) { log.inc_count_(); }
  196. ~record() { log.dec_count_(); }
  197. record append(const char *s, size_t n)
  198. { log.cur_msg.append(s, n); return *this; }
  199. template<class T>
  200. record operator<<(const T &v) { log.cur_msg << v; return *this; }
  201. };
  202. //////////////////////////////////////////////////////////////////////////////
  203. //----------------------------------------------------------------------------
  204. inline logger::record logger::trace() { return record(*this, severity::trace); }
  205. inline logger::record logger::debug() { return record(*this, severity::debug); }
  206. inline logger::record logger::info() { return record(*this, severity::info); }
  207. inline logger::record logger::notice() { return record(*this, severity::notice); }
  208. inline logger::record logger::warning() { return record(*this, severity::warning); }
  209. inline logger::record logger::error() { return record(*this, severity::error); }
  210. inline logger::record logger::fatal() { return record(*this, severity::fatal); }
  211. //----------------------------------------------------------------------------
  212. inline const char *to_string(logger::severity_t s)
  213. {
  214. extern const char * const logger_severity_strs[];
  215. return logger_severity_strs[static_cast<int>(s)];
  216. }
  217. //----------------------------------------------------------------------------
  218. #if __cpp_lib_string_view
  219. constexpr std::string_view to_string_view(logger::severity s)
  220. {
  221. constexpr std::string_view strs[] =
  222. { "TRACE", "DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "FATAL" };
  223. return strs[static_cast<int>(s)];
  224. }
  225. #endif
  226. //----------------------------------------------------------------------------
  227. } // namespace
  228. #endif // header guard