OGLplus  (0.59.0) a C++ wrapper for rendering APIs

syslog_backend.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_LOGGING_SYSLOG_BACKEND_HPP
10 #define EAGINE_LOGGING_SYSLOG_BACKEND_HPP
11 
12 #include "../config/platform.hpp"
13 #include "../flat_map.hpp"
14 #include "../memory/default_alloc.hpp"
15 #include "../memory/span_algo.hpp"
16 #include "backend.hpp"
17 #include <mutex>
18 
19 #if EAGINE_POSIX
20 #include <sys/types.h>
21 #include <syslog.h>
22 #include <unistd.h>
23 #endif
24 
25 namespace eagine {
26 //------------------------------------------------------------------------------
27 template <typename Lockable = std::mutex>
28 class syslog_log_backend : public logger_backend {
29 public:
30  syslog_log_backend(log_event_severity min_severity)
31  : _min_severity{min_severity} {
32 #if EAGINE_POSIX
33  ::openlog(
34  "OGLplus",
35  LOG_CONS | LOG_NDELAY | LOG_PID, // NOLINT(hicpp-signed-bitwise)
36  LOG_LOCAL0); // NOLINT(hicpp-signed-bitwise)
37 #endif
38  }
39 
40  auto entry_backend(identifier, log_event_severity severity) noexcept
41  -> logger_backend* final {
42  if(severity >= _min_severity) {
43  return this;
44  }
45  return nullptr;
46  }
47 
48  auto allocator() noexcept -> memory::shared_byte_allocator final {
49  return memory::default_byte_allocator();
50  }
51 
52  auto type_id() noexcept -> identifier final {
53  return EAGINE_ID(Syslog);
54  }
55 
56  void enter_scope(identifier) noexcept final {}
57 
58  void leave_scope(identifier) noexcept final {}
59 
60  void set_description(
61  identifier src,
62  logger_instance_id inst,
63  string_view name,
64  string_view desc) noexcept final {
65  EAGINE_MAYBE_UNUSED(src);
66 #if EAGINE_POSIX
67  const auto idn{src.name()};
68  ::syslog( // NOLINT(hicpp-vararg)
69  _translate(log_event_severity::info),
70  sizeof(logger_instance_id) > 4 ? "%16lx|%10.*s|name=%s, desc=%s"
71  : "%8lx|%10.*s|name=%s, desc=%s",
72  static_cast<unsigned long>(inst),
73  int(idn.size()),
74  idn.data(),
75  c_str(name).c_str(),
76  c_str(desc).c_str());
77 #endif
78  }
79 
80  auto begin_message(
81  identifier src,
82  identifier tag,
83  logger_instance_id inst,
85  string_view format) noexcept -> bool final {
86 
87  auto& msg = _new_message();
88  msg.source = src;
89  msg.tag = tag;
90  msg.instance = inst;
91  msg.format.assign(
92  sizeof(logger_instance_id) > 4 ? "%16lx|%10.*s|%10.*s|"
93  : "%8lx|%10.*s|%10.*s|");
94  _translate(format, msg);
95  return true;
96  }
97 
98  void do_add_arg(identifier arg, string_view value) noexcept {
99  auto& msg = _get_message();
100  const auto aidv = arg.value();
101  bool found = false;
102  for(auto [idx, idv] : msg.arg_idx) {
103  if(idv == aidv) {
104  found = true;
105  break;
106  }
107  }
108  if(found) {
109  msg.arg_map[aidv].assign(value);
110  } else {
111  msg.format.append(", ");
112  msg.format.append(arg.name().view());
113  msg.format.append("=");
114  msg.format.append(value);
115  }
116  }
117 
118  void add_nothing(identifier, identifier) noexcept final {}
119 
120  void add_identifier(identifier arg, identifier, identifier value) noexcept
121  final {
122  do_add_arg(arg, value.name().view());
123  }
124 
125  void add_message_id(identifier arg, identifier, message_id value) noexcept
126  final {
127  std::string temp;
128  temp.reserve(21);
129  temp.append(value.class_().name().view());
130  temp.append(".");
131  temp.append(value.method().name().view());
132  do_add_arg(arg, temp);
133  }
134 
135  void add_bool(identifier arg, identifier, bool value) noexcept final {
136  do_add_arg(arg, value ? string_view{"True"} : string_view{"False"});
137  }
138 
139  void add_integer(identifier arg, identifier, std::intmax_t value) noexcept
140  final {
141  using std::to_string;
142  do_add_arg(arg, to_string(value));
143  }
144 
145  void add_unsigned(identifier arg, identifier, std::uintmax_t value) noexcept
146  final {
147  using std::to_string;
148  do_add_arg(arg, to_string(value));
149  }
150 
151  void add_float(identifier arg, identifier, float value) noexcept final {
152  using std::to_string;
153  do_add_arg(arg, to_string(value));
154  }
155 
156  void
157  add_float(identifier arg, identifier, float, float value, float) noexcept
158  final {
159  using std::to_string;
160  do_add_arg(arg, to_string(value));
161  }
162 
163  void add_duration(
164  identifier arg,
165  identifier,
166  std::chrono::duration<float> value) noexcept final {
167  using std::to_string;
168  std::string temp(to_string(value.count()));
169  temp.append("[s]");
170  do_add_arg(arg, temp);
171  }
172 
173  void
174  add_string(identifier arg, identifier, string_view value) noexcept final {
175  using std::to_string;
176  do_add_arg(arg, value);
177  }
178 
179  void add_blob(identifier, identifier, memory::const_block) noexcept final {}
180 
181  void finish_message() noexcept final {
182  _do_log(_get_message());
183  _del_message();
184  }
185 
186  void finish_log() noexcept final {
187 #if EAGINE_POSIX
188  ::closelog();
189 #endif
190  }
191 
192  void log_chart_sample(
193  identifier,
195  identifier,
196  float) noexcept final {}
197 
198 private:
199  Lockable _lockable{};
200  log_event_severity _min_severity;
201 
202  struct _message_state {
203  identifier source;
204  identifier tag;
205  logger_instance_id instance{0};
206  std::string format;
207  flat_map<std::size_t, identifier_t> arg_idx;
208  flat_map<identifier_t, std::string> arg_map;
209  std::size_t arg_count{0};
210  };
211 
212  _message_state _the_message{};
213 
214  auto _new_message() noexcept -> auto& {
215  _lockable.lock();
216  _the_message.arg_count = 0;
217  for(auto& [idx, idv] : _the_message.arg_idx) {
218  EAGINE_MAYBE_UNUSED(idx);
219  idv = 0;
220  }
221  return _the_message;
222  }
223 
224  auto _get_message() noexcept -> auto& {
225  return _the_message;
226  }
227 
228  void _del_message() noexcept {
229  _lockable.unlock();
230  }
231 
232  static constexpr auto _translate(log_event_severity severity) noexcept
233  -> int {
234 #if EAGINE_POSIX
235  switch(severity) {
237  return LOG_CRIT;
239  return LOG_ERR;
241  return LOG_WARNING;
244  return LOG_INFO;
246  return LOG_DEBUG;
248  return LOG_NOTICE;
250  break;
251  }
252 #endif
253  EAGINE_MAYBE_UNUSED(severity);
254  return 0;
255  }
256 
257  static void _translate(string_view format, _message_state& msg) {
258  while(auto pos{find_position(format, string_view{"${"})}) {
259  const string_view prev{head(format, extract(pos))};
260  msg.format.append(prev);
261  format = skip(format, extract(pos) + 2);
262  if(auto end{find_position(format, string_view{"}"})}) {
263  msg.arg_idx[msg.arg_count++] =
264  identifier(head(format, extract(end))).value();
265  msg.format.append("%s");
266  format = skip(format, extract(end) + 1);
267  }
268  }
269  msg.format.append(format);
270  }
271 
272  template <std::size_t... I>
273  void _do_log_I(_message_state& msg, std::index_sequence<I...>) {
274  const auto source_name = msg.source.name();
275  const auto tag_name = msg.tag ? msg.tag.name().str() : std::string();
276  ::syslog( // NOLINT(hicpp-vararg)
277  _translate(log_event_severity::info),
278  msg.format.c_str(),
279  static_cast<unsigned long>(msg.instance),
280  int(source_name.size()),
281  source_name.data(),
282  int(tag_name.size()),
283  tag_name.data(),
284  msg.arg_map[msg.arg_idx[I]].c_str()...);
285  }
286 
287  template <std::size_t N>
288  auto _do_log_N(_message_state& msg) -> bool {
289  if constexpr(N > 0) {
290  if(_do_log_N<N - 1>(msg)) {
291  return true;
292  }
293  }
294  if(msg.arg_count == N) {
295  _do_log_I(msg, std::make_index_sequence<N>());
296  return true;
297  }
298  return false;
299  }
300 
301  void _do_log(_message_state& msg) {
302  _do_log_N<12>(msg);
303  }
304 };
305 //------------------------------------------------------------------------------
306 } // namespace eagine
307 
308 #endif // EAGINE_LOGGING_SYSLOG_BACKEND_HPP
static constexpr auto find_position(basic_span< T1, P1, S1 > spn, basic_span< T2, P2, S2 > what) noexcept -> optionally_valid< S1 >
Finds the position of the first occurrence of what in a span.
Definition: span_algo.hpp:260
basic_string_span< const char > string_view
Alias for const string views.
Definition: string_span.hpp:116
#define EAGINE_ID(NAME)
Macro for constructing instances of eagine::identifier.
Definition: identifier.hpp:353
@ backtrace
Backtracing log entries (the lowest severity).
static constexpr auto c_str(memory::basic_span< C, P, S > s) -> std::enable_if_t< std::is_convertible_v< memory::basic_span< C, P, S >, basic_string_span< C, P, S >>, basic_c_str< C, P, S >>
Functions that construct a basic_c_str from a basic_string_span.
Definition: string_span.hpp:226
Common code is placed in this namespace.
Definition: eagine.hpp:21
std::uintptr_t logger_instance_id
Logger object instance id type.
Definition: backend.hpp:56
static constexpr auto extract(api_result_value< Result, api_result_validity::never > &) noexcept -> Result &
Overload of extract for api_result_value.
Definition: c_api_wrap.hpp:270
basic_block< true > const_block
Alias for const byte memory span.
Definition: block.hpp:32
@ warning
Warning log entries, indicating potential problems.
@ info
Informational log entries.
static constexpr auto head(basic_span< T, P, S > s, L l) noexcept -> basic_span< T, P, S >
Returns the first l elements from the front of a span.
Definition: span_algo.hpp:99
@ error
Error log entries, indicating serious problems.
static auto format(std::string &&fmt_str) noexcept -> format_string_and_list< 0 >
Function taking a format string, returning an object for variable specification.
Definition: str_format.hpp:118
static constexpr auto skip(basic_span< T, P, S > s, L l) noexcept -> basic_span< T, P, S >
Skips a specified count of elements from the front of a span.
Definition: span_algo.hpp:60
@ debug
Debug log entries.
@ fatal
Fatal error log entries, indicating problem requiring termination.
@ trace
Trace log entries.
log_event_severity
Log event severity enumeration.
Definition: severity.hpp:18
@ stat
Statistic log entries.
basic_identifier< 10, 6, default_identifier_char_set, identifier_t > identifier
Default identifier type used throughout the project.
Definition: identifier.hpp:346

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).