qxLib
logger.h
Go to the documentation of this file.
1 /**
2 
3  @file logger.h
4  @author Khrapov
5  @date 17.06.2019
6  @copyright © Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 #pragma once
10 
13 #include <qx/logger/time_string.h>
15 #include <qx/patterns/singleton.h>
16 #include <qx/sbo/sbo_poly.h>
17 
18 #include <shared_mutex>
19 
20 /**
21  @page logger_readme logger
22  @include README.md
23 */
24 
25 /**
26  @brief Log with category
27  @param category - category to be used to manage output
28  @param eVerbosity - message verbosity
29  @param ... - user message and its format args. the format string should be without QXT
30 **/
31 #define QX_LOG_C(category, eVerbosity, ...) _QX_LOG_C(constexpr, category, eVerbosity, ##__VA_ARGS__)
32 
33 /**
34  @brief Log message
35  @param eVerbosity - message verbosity
36  @param ... - user message and its format args. the format string should be without QXT
37 **/
38 #define QX_LOG(eVerbosity, ...) QX_LOG_C(QX_GET_FILE_CATEGORY(), eVerbosity, ##__VA_ARGS__)
39 
40 /**
41  @brief Log with category and with non compile time category check
42  @param category - category to be used to manage output
43  @param eVerbosity - message verbosity
44  @param ... - user message and its format args. the format string should be without QXT
45 **/
46 #define QX_LOG_REF(category, eVerbosity, ...) _QX_LOG_C(, category, eVerbosity, ##__VA_ARGS__)
47 
48 namespace qx
49 {
50 
51 /**
52 
53  @class logger
54  @brief Logger class
55  @author Khrapov
56  @date 10.01.2020
57 
58 **/
59 class logger
60 {
61 public:
62  using logger_sbo = sbo_poly<
64 #if QX_CLANG || QX_APPLE_CLANG || QX_GNU
65  1024
66 #else
67  512
68 #endif
69  >;
70 
72  {
73  // For best performance, do not allocate anything in this function and return the modified sMessage object.
74  // See default_formatter for an example.
75  using format_function = std::function<string(
76  const category& category,
77  verbosity eVerbosity,
78  string_view svFile,
79  string_view svFunction,
80  int nLine,
81  string sMessage)>;
82 
83  verbosity eRuntimeVerbosity = verbosity::detailed;
84  format_function formatFunction;
85  };
86 
87  using category_data_map = std::unordered_map<string_view, category_data>;
89 
90 public:
91  logger() noexcept;
92  virtual ~logger() noexcept;
93 
94  /**
95  @brief Add an output stream to the logger
96  @tparam stream_t - stream type, derived from base_logger_stream
97  @param stream - stream object
98  **/
99  template<sbo_poly_assignable_c<base_logger_stream> stream_t>
100  void add_stream(stream_t stream) noexcept;
101 
102  /**
103  @brief Add custom rules for category
104  @param category - category to register
105  @param data - category data
106  **/
107  void register_category(const category& category, category_data data) noexcept;
108 
109  /**
110  @brief Add custom rules for category
111  @param svCategoryName - category name, must stay valid while the logger is alive (category existence is not checked)
112  @param data - category data
113  **/
114  void register_category(string_view svCategoryName, category_data data) noexcept;
115 
116  /**
117  @brief Log to all streams
118  @warning All input args must be ready for async work (i.e. be stable)
119  @param category - code category
120  @param eVerbosity - message verbosity
121  @param svFile - file name string
122  @param svFunction - function name string
123  @param nLine - code line number
124  @param message - user message string
125  **/
126  virtual void log(
127  const category& category,
128  verbosity eVerbosity,
129  string_view svFile,
130  string_view svFunction,
131  int nLine,
132  logger_string_pool::item message);
133 
134  /**
135  @brief Flush all streams
136  **/
137  virtual void flush();
138 
139  /**
140  @brief Reset logger and clear all streams
141  **/
142  virtual void reset() noexcept;
143 
144  /**
145  @brief Returns true if a log with given category and verbosity will be logged
146  @details Typically you don't want to use it
147  It may be useful with async logging to avoid unnecessary formatting and queueing
148  @param category - code category
149  @param eVerbosity - message verbosity
150  @retval - true if a log with given category and verbosity will be logged
151  **/
152  bool log_required(const category& category, verbosity eVerbosity) const noexcept;
153 
154  // only for internal usage in macros
155  logger_string_pool* _get_string_pool() noexcept;
156 
157 protected:
158  /**
159  @brief The default log line formatter
160  @param category - code category
161  @param eVerbosity - message verbosity
162  @param svFile - file name string
163  @param svFunction - function name string
164  @param nLine - code line number
165  @param sMessage - user message string
166  @retval - the formatted log line (the same object as sMessage)
167  **/
168  static string default_formatter(
169  const category& category,
170  verbosity eVerbosity,
171  string_view svFile,
172  string_view svFunction,
173  int nLine,
174  string sMessage) noexcept;
175 
176  /**
177  @brief Get verbosity prefix
178  @param eVerbosity - message verbosity
179  @retval - verbosity prefix
180  **/
181  static constexpr string_view get_verbosity_prefix(verbosity eVerbosity) noexcept;
182 
183 private:
184  QX_PERF_SHARED_MUTEX(m_StreamsMutex);
185  std::vector<logger_sbo> m_Streams;
186 
187  QX_PERF_SHARED_MUTEX(m_RegisteredCategoriesMutex);
188  category_data_map m_RegisteredCategories;
189 
190  logger_string_pool m_StringsPool;
191 };
192 
193 /**
194 
195  @class logger_singleton
196  @brief Default logger instance
197  @author Khrapov
198  @date 19.08.2021
199 
200 **/
202 {
203 public:
204  logger& get_logger() noexcept
205  {
206  return m_Logger;
207  }
208 
209 private:
210  logger m_Logger;
211 };
212 
213 // Change this variable to override the logger instance used in QX_LOG macros
214 inline logger* g_pGlobalLogger = nullptr;
215 
216 /**
217  @brief Get the logger instance used in QX_LOG macros
218  @retval - logger instance
219 **/
220 inline logger& get_logger() noexcept
221 {
222  return g_pGlobalLogger ? *g_pGlobalLogger : logger_singleton::get_instance().get_logger();
223 }
224 
225 } // namespace qx
226 
227 #ifndef _QX_LOG_C
228 // __FUNCTION__ isn't a char array on linux, so we need to convert it
229  #define _QX_LOG_C(verbosityCheckKeyword, category, eVerbosity, ...) \
230  do \
231  { \
232  verbosityCheckKeyword const auto& _category = category; \
233  if verbosityCheckKeyword (eVerbosity >= _category.get_verbosity()) \
234  { \
235  qx::logger& _logger = qx::get_logger(); \
236  _logger.log( \
237  _category, \
238  eVerbosity, \
239  QX_SHORT_FILE, \
240  qx::convert_string_literal<qx::char_type, __FUNCTION__>(), \
241  QX_LINE, \
242  _QX_MACRO_USER_MESSAGE(_logger._get_string_pool(), __VA_ARGS__)); \
243  } \
244  } while (false)
245 #endif
246 
247 #include <qx/logger/logger.inl>
Base class for logger streams.
A category is a class that identifies a particular piece of code. This code can be located in differe...
Definition: category.h:59
Default logger instance.
Definition: logger.h:202
Logger class.
Definition: logger.h:60
bool log_required(const category &category, verbosity eVerbosity) const noexcept
Returns true if a log with given category and verbosity will be logged.
Definition: logger.inl:97
void add_stream(stream_t stream) noexcept
Add an output stream to the logger.
Definition: logger.inl:24
void register_category(const category &category, category_data data) noexcept
Add custom rules for category.
Definition: logger.inl:30
virtual void reset() noexcept
Reset logger and clear all streams.
Definition: logger.inl:89
virtual void log(const category &category, verbosity eVerbosity, string_view svFile, string_view svFunction, int nLine, logger_string_pool::item message)
Log to all streams.
Definition: logger.inl:41
static constexpr string_view get_verbosity_prefix(verbosity eVerbosity) noexcept
Get verbosity prefix.
Definition: logger.inl:169
static string default_formatter(const category &category, verbosity eVerbosity, string_view svFile, string_view svFunction, int nLine, string sMessage) noexcept
The default log line formatter.
Definition: logger.inl:116
virtual void flush()
Flush all streams.
Definition: logger.inl:82
Small Buffer Object for polymorphic classes.
Definition: sbo_poly.h:58
Fixed-size atomic string pool.
Definition: string_pool.h:34
Inherit the necessary singleton class from this.
logger & get_logger() noexcept
Get the logger instance used in QX_LOG macros.
Definition: logger.h:220