qxLib
base_logger_stream.inl
Go to the documentation of this file.
1 /**
2 
3  @file base_logger_stream.inl
4  @author Khrapov
5  @date 30.07.2021
6  @copyright © Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 
10 QX_DEFINE_FILE_CATEGORY(CatLogger);
11 
12 namespace qx
13 {
14 
15 inline base_logger_stream::base_logger_stream(bool bAlwaysFlush) : m_bAlwaysFlush(bAlwaysFlush)
16 {
17  register_unit(k_svDefaultUnit, { verbosity::log });
18 }
19 
21  verbosity eVerbosity,
22  const category& category,
23  string_view svFile,
24  string_view svFunction,
25  int nLine,
26  string_view swLogMessage)
27 {
28  QX_PERF_SCOPE("Log");
29 
30  const auto optLogUnit = get_unit_info(category, eVerbosity, svFile, svFunction);
31  if (!optLogUnit)
32  return;
33 
34  std::lock_guard lock(m_LoggerStreamMutex);
35 
36  auto& buffers = get_log_buffer();
37  buffers.clear();
38 
39  auto formatFunc = optLogUnit->pUnitInfo->formatFunc;
40  if (!formatFunc)
41  {
42  formatFunc = [this](
43  logger_buffer& buffers,
44  verbosity eVerbosity,
45  const qx::category& category,
46  string_view svFile,
47  string_view svFunction,
48  int nLine,
49  string_view swLogMessage)
50  {
51  format_line(buffers, eVerbosity, category, svFile, svFunction, nLine, swLogMessage);
52  };
53  }
54 
55  {
56  QX_PERF_SCOPE("Log formatting");
57  formatFunc(buffers, eVerbosity, category, svFile, svFunction, nLine, swLogMessage);
58  }
59 
60  if (!buffers.sMessage.empty())
61  {
62  do_log(buffers.sMessage, *optLogUnit, buffers.colors, eVerbosity);
63  if (m_bAlwaysFlush)
64  flush();
65  }
66 }
67 
68 inline void base_logger_stream::register_unit(string_view svUnitName, const log_unit_info& unit) noexcept
69 {
70  if (!svUnitName.empty())
71  m_Units.emplace(string_hash(svUnitName), unit);
72 }
73 
74 inline void base_logger_stream::deregister_unit(string_view svUnitName) noexcept
75 {
76  m_Units.erase(string_hash(svUnitName));
77 }
78 
79 inline std::optional<log_unit> base_logger_stream::get_unit_info(
80  const category& category,
81  verbosity eVerbosity,
82  string_view svFile,
83  string_view svFunction) const noexcept
84 {
85  QX_PERF_SCOPE();
86 
87  auto find_unit = [this](string_view svUnit)
88  {
89  return !svUnit.empty() ? m_Units.find(string_hash(svUnit)) : m_Units.cend();
90  };
91 
92  std::optional<log_unit> optLogUnit = std::nullopt;
93 
94  if (auto it = find_unit(category.get_name()); it != m_Units.cend())
95  optLogUnit = { &it->second, category.get_name() };
96  else if (it = find_unit(svFile); it != m_Units.cend())
97  optLogUnit = { &it->second, svFile };
98  else if (it = find_unit(svFunction); it != m_Units.cend())
99  optLogUnit = { &it->second, svFunction };
100  else if (it = find_unit(k_svDefaultUnit); it != m_Units.cend())
101  optLogUnit = { &it->second, k_svDefaultUnit };
102 
103  if (optLogUnit && optLogUnit->pUnitInfo && eVerbosity >= optLogUnit->pUnitInfo->eMinVerbosity)
104  return optLogUnit;
105  else
106  return std::nullopt;
107 }
108 
110  string& sTime,
111  char_type chDateDelimiter,
112  char_type chTimeDelimiter) noexcept
113 {
114  std::time_t t = std::time(nullptr);
115  QX_PUSH_SUPPRESS_MSVC_WARNINGS(4996);
116  std::tm* now = std::localtime(&t);
117  QX_POP_SUPPRESS_WARNINGS();
118 
119  sTime.append_format(
120  QX_TEXT("{:02}{}{:02}{}{:04}_{:02}{}{:02}{}{:02}"),
121  now->tm_mday,
122  chDateDelimiter,
123  now->tm_mon,
124  chDateDelimiter,
125  now->tm_year + 1900,
126  now->tm_hour,
127  chTimeDelimiter,
128  now->tm_min,
129  chTimeDelimiter,
130  now->tm_sec);
131 }
132 
134 {
135  return m_Buffer;
136 }
137 
139  logger_buffer& buffers,
140  verbosity eVerbosity,
141  const category& category,
142  string_view svFile,
143  string_view svFunction,
144  int nLine,
145  string_view swLogMessage) noexcept
146 {
147  switch (eVerbosity)
148  {
149  case verbosity::very_verbose:
150  buffers.sMessage = QX_TEXT("[VV][");
151  break;
152 
153  case verbosity::verbose:
154  buffers.sMessage = QX_TEXT("[V][");
155  break;
156 
157  case verbosity::important:
158  buffers.sMessage = QX_TEXT("[I][");
159  break;
160 
161  case verbosity::warning:
162  buffers.sMessage = QX_TEXT("[W][");
163  break;
164 
165  case verbosity::error:
166  buffers.sMessage = QX_TEXT("[E][");
167  break;
168 
169  case verbosity::critical:
170  buffers.sMessage = QX_TEXT("[C][");
171  break;
172 
173  default:
174  buffers.sMessage = QX_TEXT(" [");
175  break;
176  }
177 
178  append_time_string(buffers.sMessage, QX_TEXT('.'), QX_TEXT(':'));
179  buffers.sMessage += QX_TEXT("][");
180 
181  string_view svCategory = category.get_name();
182  if (!svCategory.empty())
183  {
184  buffers.sMessage += svCategory;
185  buffers.sMessage += QX_TEXT("][");
186  }
187 
188  buffers.sMessage.append_format(QX_TEXT("{}::{}::{}] {}\n"), svFile, svFunction, nLine, swLogMessage);
189 
190  if (!svCategory.empty())
191  if (auto nPos = buffers.sMessage.find(svCategory); nPos != string::npos)
192  buffers.colors.push_back({ { nPos, nPos + svCategory.size() }, category.get_color() });
193 }
194 
195 } // namespace qx
#define QX_DEFINE_FILE_CATEGORY(_category)
Define file category You can access this value via QX_FILE_CATEGORY() This category will not be expor...
Definition: category.h:29
static void append_time_string(string &sTime, char_type chDateDelimiter, char_type chTimeDelimiter) noexcept
Format time string to the buffer.
void log(verbosity eVerbosity, const category &category, string_view svFile, string_view svFunction, int nLine, string_view swLogMessage)
Output to stream.
std::optional< log_unit > get_unit_info(const category &category, verbosity eVerbosity, string_view svFile, string_view svFunction) const noexcept
Try to find log unit info based on trace location info.
logger_buffer & get_log_buffer() noexcept
Get string buffers.
virtual void flush()=0
Flush stream.
void deregister_unit(string_view svUnitName) noexcept
Deregister logger unit.
base_logger_stream(bool bAlwaysFlush)
base_logger_stream object constructor
void register_unit(string_view svUnitName, const log_unit_info &unit) noexcept
Register logger unit.
virtual void format_line(logger_buffer &buffers, verbosity eVerbosity, const category &category, string_view svFile, string_view svFunction, int nLine, string_view swLogMessage) noexcept
Format logger line.
String hash object.
Definition: string_hash.h:38
A category is a class that identifies a particular piece of code. This code can be located in differe...
Definition: category.h:56
constexpr string_view get_name() const noexcept
Get category name.
Definition: category.inl:26
constexpr const color & get_color() const noexcept
Get category color.
Definition: category.inl:31