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

ostream_backend.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_LOGGING_OSTREAM_BACKEND_HPP
10 #define EAGINE_LOGGING_OSTREAM_BACKEND_HPP
11 
12 #include "../base64dump.hpp"
13 #include "../memory/aligned_block.hpp"
14 #include "../memory/stack_alloc.hpp"
15 #include "backend.hpp"
16 #include <mutex>
17 #include <ostream>
18 
19 namespace eagine {
20 //------------------------------------------------------------------------------
21 template <typename Lockable = std::mutex>
22 class ostream_log_backend : public logger_backend {
23 private:
24  Lockable _lockable{};
25  std::ostream& _out;
26  log_event_severity _min_severity;
27  const std::chrono::steady_clock::time_point _start;
28  memory::aligned_block<63 * 1024> _alloc_block{};
29 
30 protected:
31  virtual void flush() noexcept {}
32 
33 public:
34  ostream_log_backend(
35  std::ostream& out,
36  log_event_severity min_severity) noexcept
37  : _out{out}
38  , _min_severity{min_severity}
39  , _start{std::chrono::steady_clock::now()} {
40  try {
41  std::unique_lock lock{_lockable};
42  _out << "<?xml version='1.0' encoding='UTF-8'?>\n";
43  _out << "<log start='" << _start.time_since_epoch().count()
44  << "'>\n";
45  } catch(...) {
46  }
47  }
48 
49  ostream_log_backend(ostream_log_backend&&) = delete;
50  ostream_log_backend(const ostream_log_backend&) = delete;
51  auto operator=(ostream_log_backend&&) = delete;
52  auto operator=(const ostream_log_backend&) = delete;
53 
54  auto allocator() noexcept -> memory::shared_byte_allocator final {
55  return memory::default_byte_allocator();
56  // TODO
57  // return {memory::stack_byte_allocator_only<>{_alloc_block}};
58  }
59 
60  auto type_id() noexcept -> identifier final {
61  return EAGINE_ID(OutStream);
62  }
63 
64  auto entry_backend(identifier, log_event_severity severity) noexcept
65  -> logger_backend* final {
66  if(severity >= _min_severity) {
67  return this;
68  }
69  return nullptr;
70  }
71 
72  void enter_scope(identifier scope) noexcept final {
73  try {
74  _lockable.lock();
75  _out << "<s name='" << scope.name() << "'>\n";
76  } catch(...) {
77  }
78  }
79 
80  void leave_scope(identifier) noexcept final {
81  try {
82  _lockable.lock();
83  _out << "</s>\n";
84  } catch(...) {
85  }
86  }
87 
88  void set_description(
89  identifier source,
90  logger_instance_id instance,
91  string_view display_name,
92  string_view description) noexcept final {
93  try {
94  std::unique_lock lock{_lockable};
95  _out << "<d";
96  _out << " src='" << source.name() << "'";
97  _out << " iid='" << instance << "'";
98  _out << " dn='" << display_name << "'";
99  _out << " desc='" << description << "'";
100  _out << "/>\n";
101  flush();
102  } catch(...) {
103  }
104  }
105 
106  auto begin_message(
107  identifier source,
108  identifier tag,
109  logger_instance_id instance,
110  log_event_severity severity,
111  string_view format) noexcept -> bool final {
112  try {
113  const auto now = std::chrono::steady_clock::now();
114  const auto sec = std::chrono::duration<float>(now - _start);
115  _lockable.lock();
116  _out << "<m";
117  _out << " lvl='" << enumerator_name(severity) << "'";
118  _out << " src='" << source.name() << "'";
119  if(tag) {
120  _out << " tag='" << tag.name() << "'";
121  }
122  _out << " iid='" << instance << "'";
123  _out << " ts='" << sec.count() << "'";
124  _out << ">";
125  _out << "<f>" << format << "</f>";
126  } catch(...) {
127  }
128  return true;
129  }
130 
131  void add_nothing(identifier arg, identifier tag) noexcept final {
132  try {
133  _out << "<a n='" << arg.name() << "' t='" << tag.name() << "'/>";
134  } catch(...) {
135  }
136  }
137 
138  void add_identifier(
139  identifier arg,
140  identifier tag,
141  identifier value) noexcept final {
142  try {
143  _out << "<a n='" << arg.name() << "' t='" << tag.name() << "'>"
144  << value.name() << "</a>";
145  } catch(...) {
146  }
147  }
148 
149  void add_message_id(
150  identifier arg,
151  identifier tag,
152  message_id msg_id) noexcept final {
153  try {
154  _out << "<a n='" << arg.name() << "' t='" << tag.name() << "'>"
155  << msg_id.class_().name() << "." << msg_id.method().name()
156  << "</a>";
157  } catch(...) {
158  }
159  }
160 
161  void add_bool(identifier arg, identifier tag, bool value) noexcept final {
162  try {
163  _out << "<a n='" << arg.name() << "' t='" << tag.name() << "'>"
164  << (value ? "true" : "false") << "</a>";
165  } catch(...) {
166  }
167  }
168 
169  void add_integer(
170  identifier arg,
171  identifier tag,
172  std::intmax_t value) noexcept final {
173  try {
174  _out << "<a n='" << arg.name() << "' t='" << tag.name() << "'>"
175  << value << "</a>";
176  } catch(...) {
177  }
178  }
179 
180  void add_unsigned(
181  identifier arg,
182  identifier tag,
183  std::uintmax_t value) noexcept final {
184  try {
185  _out << "<a n='" << arg.name() << "' t='" << tag.name() << "'>"
186  << value << "</a>";
187  } catch(...) {
188  }
189  }
190 
191  void add_float(identifier arg, identifier tag, float value) noexcept final {
192  try {
193  _out << "<a n='" << arg.name() << "' t='" << tag.name() << "'>"
194  << value << "</a>";
195  } catch(...) {
196  }
197  }
198 
199  void add_float(
200  identifier arg,
201  identifier tag,
202  float min,
203  float value,
204  float max) noexcept final {
205  try {
206  _out << "<a n='" << arg.name() << "' t='" << tag.name() << "' min='"
207  << min << "' max='" << max << "'>" << value << "</a>";
208  } catch(...) {
209  }
210  }
211 
212  void add_duration(
213  identifier arg,
214  identifier tag,
215  std::chrono::duration<float> value) noexcept final {
216  try {
217  _out << "<a n='" << arg.name() << "' t='" << tag.name()
218  << "' u='s'>" << value.count() << "</a>";
219  } catch(...) {
220  }
221  }
222 
223  void add_blob(
224  identifier arg,
225  identifier tag,
226  memory::const_block value) noexcept final {
227  try {
228  _out << "<a n='" << arg.name() << "' t='" << tag.name()
229  << "' blob='true'>" << base64dump(value) << "</a>";
230  } catch(...) {
231  }
232  }
233 
234  void add_string(identifier arg, identifier tag, string_view value) noexcept
235  final {
236  try {
237  _out << "<a n='" << arg.name() << "' t='" << tag.name() << "'>"
238  << value << "</a>";
239  } catch(...) {
240  }
241  }
242 
243  void finish_message() noexcept final {
244  try {
245  _out << "</m>\n";
246  flush();
247  _lockable.unlock();
248  } catch(...) {
249  }
250  }
251 
252  void finish_log() noexcept final {
253  try {
254  std::unique_lock lock{_lockable};
255  _out << "</log>\n" << std::flush;
256  flush();
257  } catch(...) {
258  }
259  }
260 
261  void log_chart_sample(
262  identifier source,
263  logger_instance_id instance,
264  identifier series,
265  float value) noexcept final {
266  try {
267  const auto now = std::chrono::steady_clock::now();
268  const auto sec = std::chrono::duration<float>(now - _start);
269  std::unique_lock lock{_lockable};
270  _out << "<c";
271  _out << " src='" << source.name() << "'";
272  _out << " iid='" << instance << "'";
273  _out << " ser='" << series.name() << "'";
274  _out << " ts='" << sec.count() << "'";
275  _out << " v='" << value << "'";
276  _out << "/>\n";
277  } catch(...) {
278  }
279  }
280 
281  ~ostream_log_backend() noexcept override {
282  finish_log();
283  }
284 };
285 //------------------------------------------------------------------------------
286 } // namespace eagine
287 
288 #endif // EAGINE_LOGGING_OSTREAM_BACKEND_HPP
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
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
basic_block< true > const_block
Alias for const byte memory span.
Definition: block.hpp:32
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
log_event_severity
Log event severity enumeration.
Definition: severity.hpp:18
auto operator=(interface &&)=delete
Not move assignable.
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).