qxLib
logger.inl
Go to the documentation of this file.
1 /**
2 
3  @file logger.inl
4  @author Khrapov
5  @date 17.06.2019
6  @copyright © Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 inline logger::logger() noexcept
14 {
15  add_stream(fwrite_logger_stream());
16 }
17 
18 inline logger::~logger() noexcept
19 {
20  logger::flush();
21 }
22 
23 template<sbo_poly_assignable_c<base_logger_stream> stream_t>
24 inline void logger::add_stream(stream_t stream) noexcept
25 {
26  std::unique_lock _(m_StreamsMutex);
27  m_Streams.emplace_back(std::move(stream));
28 }
29 
30 inline void logger::register_category(const category& category, category_data data) noexcept
31 {
32  register_category(category.get_name(), std::move(data));
33 }
34 
35 inline void logger::register_category(string_view svCategoryName, category_data data) noexcept
36 {
37  std::unique_lock _(m_RegisteredCategoriesMutex);
38  m_RegisteredCategories.emplace(svCategoryName, std::move(data));
39 }
40 
41 inline void logger::log(
42  const category& category,
43  verbosity eVerbosity,
44  string_view svFile,
45  string_view svFunction,
46  int nLine,
48 {
49  string sMessage = std::move(message.sValue);
50 
51  if (log_required(category, eVerbosity))
52  {
53  bool bFormatted = false;
54  {
55  std::shared_lock _(m_RegisteredCategoriesMutex);
56  if (auto itRegisteredCategory = m_RegisteredCategories.find(category.get_name());
57  itRegisteredCategory != m_RegisteredCategories.end())
58  {
59  const category_data& data = itRegisteredCategory->second;
60  if (data.formatFunction)
61  {
62  sMessage =
63  data.formatFunction(category, eVerbosity, svFile, svFunction, nLine, std::move(sMessage));
64  bFormatted = true;
65  }
66  }
67  }
68 
69  if (!bFormatted)
70  sMessage = default_formatter(category, eVerbosity, svFile, svFunction, nLine, std::move(sMessage));
71 
72  {
73  std::shared_lock _(m_StreamsMutex);
74  for (auto& stream : m_Streams)
75  stream->log(category, eVerbosity, sMessage);
76  }
77  }
78 
79  m_StringsPool.release(std::move(sMessage), message.nIndex);
80 }
81 
82 inline void logger::flush()
83 {
84  std::shared_lock _(m_StreamsMutex);
85  for (auto& stream : m_Streams)
86  stream->flush();
87 }
88 
89 inline void logger::reset() noexcept
90 {
91  flush();
92 
93  std::unique_lock _(m_StreamsMutex);
94  m_Streams.clear();
95 }
96 
97 inline bool logger::log_required(const category& category, verbosity eVerbosity) const noexcept
98 {
99  std::shared_lock _(m_RegisteredCategoriesMutex);
100 
101  if (auto itRegisteredCategory = m_RegisteredCategories.find(category.get_name());
102  itRegisteredCategory != m_RegisteredCategories.end())
103  {
104  const category_data& data = itRegisteredCategory->second;
105  return eVerbosity >= data.eRuntimeVerbosity;
106  }
107 
108  return eVerbosity >= verbosity::log;
109 }
110 
111 inline logger::logger_string_pool* logger::_get_string_pool() noexcept
112 {
113  return &m_StringsPool;
114 }
115 
117  const category& category,
118  verbosity eVerbosity,
119  string_view svFile,
120  string_view svFunction,
121  int nLine,
122  string sMessage) noexcept
123 {
124  // avoid extra allocation, insert prefix inplace
125 
126  const string_view svVerbosityPrefix = get_verbosity_prefix(eVerbosity);
127  const string_view svCategory = category.get_name();
128  const bool bAddCategory = !svCategory.empty() && svCategory != CatDefault.get_name();
129 
130  constexpr size_t nTimeSize = 19;
131  const size_t nCategorySize = bAddCategory ? svCategory.size() + 2 : 0;
132  const size_t nPrefixSize = svVerbosityPrefix.size() + nTimeSize + 2 + nCategorySize;
133 
134  sMessage.insert(0, QXT("\0"), nPrefixSize);
135  size_t nPos = 0;
136 
137  std::memcpy(
138  sMessage.data() + nPos,
139  svVerbosityPrefix.data(),
140  svVerbosityPrefix.size() * sizeof(string_view::value_type));
141  nPos += svVerbosityPrefix.size();
142 
143  append_time_string(sMessage.data() + nPos, QXT('.'), QXT(':'));
144  nPos += nTimeSize;
145 
146  sMessage[nPos] = QXT(']');
147  nPos += 1;
148 
149  if (bAddCategory)
150  {
151  sMessage[nPos] = QXT('[');
152  nPos += 1;
153 
154  std::memcpy(sMessage.data() + nPos, svCategory.data(), svCategory.size() * sizeof(string::value_type));
155  nPos += svCategory.size();
156 
157  sMessage[nPos] = QXT(']');
158  nPos += 1;
159  }
160 
161  sMessage[nPos] = QXT(' ');
162  nPos += 1;
163 
164  sMessage += QXT('\n');
165 
166  return sMessage;
167 }
168 
169 constexpr string_view logger::get_verbosity_prefix(verbosity eVerbosity) noexcept
170 {
171  switch (eVerbosity)
172  {
173  case verbosity::detailed:
174  return QXT("[D][");
175 
176  case verbosity::verbose:
177  return QXT("[V][");
178 
179  case verbosity::important:
180  return QXT("[I][");
181 
182  case verbosity::warning:
183  return QXT("[W][");
184 
185  case verbosity::error:
186  return QXT("[E][");
187 
188  case verbosity::critical:
189  return QXT("[C][");
190 
191  default:
192  return QXT(" [");
193  }
194 }
195 
196 } // namespace qx
A category is a class that identifies a particular piece of code. This code can be located in differe...
Definition: category.h:59
constexpr string_view get_name() const noexcept
Get category name.
Definition: category.inl:26
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
Fixed-size atomic string pool.
Definition: string_pool.h:34
void release(string sValue, int nIndex)
Return a string back to the pool.
Definition: string_pool.inl:58
void append_time_string(out_it_t it, char_type chDateDelimiter, char_type chTimeDelimiter) noexcept
Format time string to the buffer.
Definition: time_string.h:27