WireCellToolkit
Wire Cell Simulation, Signal Process and Reconstruction Toolki for Liquid Argon Detectors
logger_impl.h
Go to the documentation of this file.
1 //
2 // Copyright(c) 2015 Gabi Melman.
3 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
4 //
5 
6 #pragma once
7 
9 
10 #include <memory>
11 #include <string>
12 
13 #define SPDLOG_CATCH_AND_HANDLE \
14  catch (const std::exception &ex) \
15  { \
16  err_handler_(ex.what()); \
17  } \
18  catch (...) \
19  { \
20  err_handler_("Unknown exception in logger"); \
21  }
22 
23 // create logger with given name, sinks and the default pattern formatter
24 // all other ctors will call this one
25 template<typename It>
26 inline spdlog::logger::logger(std::string logger_name, It begin, It end)
27  : name_(std::move(logger_name))
28  , sinks_(begin, end)
29 {
30 }
31 
32 // ctor with sinks as init list
33 inline spdlog::logger::logger(std::string logger_name, sinks_init_list sinks_list)
34  : logger(std::move(logger_name), sinks_list.begin(), sinks_list.end())
35 {
36 }
37 
38 // ctor with single sink
39 inline spdlog::logger::logger(std::string logger_name, spdlog::sink_ptr single_sink)
40  : logger(std::move(logger_name), {std::move(single_sink)})
41 {
42 }
43 
44 inline spdlog::logger::~logger() = default;
45 
46 inline void spdlog::logger::set_formatter(std::unique_ptr<spdlog::formatter> f)
47 {
48  for (auto &sink : sinks_)
49  {
50  sink->set_formatter(f->clone());
51  }
52 }
53 
54 inline void spdlog::logger::set_pattern(std::string pattern, pattern_time_type time_type)
55 {
56  auto new_formatter = details::make_unique<spdlog::pattern_formatter>(std::move(pattern), time_type);
57  set_formatter(std::move(new_formatter));
58 }
59 
60 template<typename... Args>
61 inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const char *fmt, const Args &... args)
62 {
63  if (!should_log(lvl))
64  {
65  return;
66  }
67 
68  try
69  {
72  fmt::format_to(buf, fmt, args...);
73  details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
74  sink_it_(log_msg);
75  }
77 }
78 
79 template<typename... Args>
80 inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Args &... args)
81 {
82  log(source_loc{}, lvl, fmt, args...);
83 }
84 
85 inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const char *msg)
86 {
87  if (!should_log(lvl))
88  {
89  return;
90  }
91 
92  try
93  {
94  details::log_msg log_msg(source, &name_, lvl, spdlog::string_view_t(msg));
95  sink_it_(log_msg);
96  }
98 }
99 
100 inline void spdlog::logger::log(level::level_enum lvl, const char *msg)
101 {
102  log(source_loc{}, lvl, msg);
103 }
104 
105 template<class T, typename std::enable_if<std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
106 inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const T &msg)
107 {
108  if (!should_log(lvl))
109  {
110  return;
111  }
112  try
113  {
114  details::log_msg log_msg(source, &name_, lvl, msg);
115  sink_it_(log_msg);
116  }
118 }
119 
120 template<class T, typename std::enable_if<std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
121 inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
122 {
123  log(source_loc{}, lvl, msg);
124 }
125 
126 template<class T, typename std::enable_if<!std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
127 inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const T &msg)
128 {
129  if (!should_log(lvl))
130  {
131  return;
132  }
133  try
134  {
136  fmt::memory_buffer buf;
137  fmt::format_to(buf, "{}", msg);
138  details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
139  sink_it_(log_msg);
140  }
142 }
143 
144 template<class T, typename std::enable_if<!std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
145 inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
146 {
147  log(source_loc{}, lvl, msg);
148 }
149 
150 template<typename... Args>
151 inline void spdlog::logger::trace(const char *fmt, const Args &... args)
152 {
153  log(level::trace, fmt, args...);
154 }
155 
156 template<typename... Args>
157 inline void spdlog::logger::debug(const char *fmt, const Args &... args)
158 {
159  log(level::debug, fmt, args...);
160 }
161 
162 template<typename... Args>
163 inline void spdlog::logger::info(const char *fmt, const Args &... args)
164 {
165  log(level::info, fmt, args...);
166 }
167 
168 template<typename... Args>
169 inline void spdlog::logger::warn(const char *fmt, const Args &... args)
170 {
171  log(level::warn, fmt, args...);
172 }
173 
174 template<typename... Args>
175 inline void spdlog::logger::error(const char *fmt, const Args &... args)
176 {
177  log(level::err, fmt, args...);
178 }
179 
180 template<typename... Args>
181 inline void spdlog::logger::critical(const char *fmt, const Args &... args)
182 {
183  log(level::critical, fmt, args...);
184 }
185 
186 template<typename T>
187 inline void spdlog::logger::trace(const T &msg)
188 {
189  log(level::trace, msg);
190 }
191 
192 template<typename T>
193 inline void spdlog::logger::debug(const T &msg)
194 {
195  log(level::debug, msg);
196 }
197 
198 template<typename T>
199 inline void spdlog::logger::info(const T &msg)
200 {
201  log(level::info, msg);
202 }
203 
204 template<typename T>
205 inline void spdlog::logger::warn(const T &msg)
206 {
207  log(level::warn, msg);
208 }
209 
210 template<typename T>
211 inline void spdlog::logger::error(const T &msg)
212 {
213  log(level::err, msg);
214 }
215 
216 template<typename T>
217 inline void spdlog::logger::critical(const T &msg)
218 {
219  log(level::critical, msg);
220 }
221 
222 #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
223 
224 inline void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target)
225 {
226  int wbuf_size = static_cast<int>(wbuf.size());
227  if (wbuf_size == 0)
228  {
229  return;
230  }
231 
232  auto result_size = ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, NULL, 0, NULL, NULL);
233 
234  if (result_size > 0)
235  {
236  target.resize(result_size);
237  ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, &target.data()[0], result_size, NULL, NULL);
238  }
239  else
240  {
241  throw spdlog::spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError()));
242  }
243 }
244 
245 template<typename... Args>
246 inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args)
247 {
248  if (!should_log(lvl))
249  {
250  return;
251  }
252 
253  try
254  {
255  // format to wmemory_buffer and convert to utf8
257  fmt::wmemory_buffer wbuf;
258  fmt::format_to(wbuf, fmt, args...);
259  fmt::memory_buffer buf;
260  wbuf_to_utf8buf(wbuf, buf);
261  details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
262  sink_it_(log_msg);
263  }
265 }
266 
267 template<typename... Args>
268 inline void spdlog::logger::log(level::level_enum lvl, const wchar_t *fmt, const Args &... args)
269 {
270  log(source_loc{}, lvl, fmt, args...);
271 }
272 
273 template<typename... Args>
274 inline void spdlog::logger::trace(const wchar_t *fmt, const Args &... args)
275 {
276  log(level::trace, fmt, args...);
277 }
278 
279 template<typename... Args>
280 inline void spdlog::logger::debug(const wchar_t *fmt, const Args &... args)
281 {
282  log(level::debug, fmt, args...);
283 }
284 
285 template<typename... Args>
286 inline void spdlog::logger::info(const wchar_t *fmt, const Args &... args)
287 {
288  log(level::info, fmt, args...);
289 }
290 
291 template<typename... Args>
292 inline void spdlog::logger::warn(const wchar_t *fmt, const Args &... args)
293 {
294  log(level::warn, fmt, args...);
295 }
296 
297 template<typename... Args>
298 inline void spdlog::logger::error(const wchar_t *fmt, const Args &... args)
299 {
300  log(level::err, fmt, args...);
301 }
302 
303 template<typename... Args>
304 inline void spdlog::logger::critical(const wchar_t *fmt, const Args &... args)
305 {
306  log(level::critical, fmt, args...);
307 }
308 
309 #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
310 
311 //
312 // name and level
313 //
314 inline const std::string &spdlog::logger::name() const
315 {
316  return name_;
317 }
318 
320 {
321  level_.store(log_level);
322 }
323 
325 {
326  err_handler_ = std::move(err_handler);
327 }
328 
330 {
331  return err_handler_;
332 }
333 
335 {
336  try
337  {
338  flush_();
339  }
341 }
342 
344 {
345  flush_level_.store(log_level);
346 }
347 
349 {
350  return static_cast<spdlog::level::level_enum>(flush_level_.load(std::memory_order_relaxed));
351 }
352 
354 {
355  auto flush_level = flush_level_.load(std::memory_order_relaxed);
356  return (msg.level >= flush_level) && (msg.level != level::off);
357 }
358 
360 {
361  return static_cast<spdlog::level::level_enum>(SPDLOG_ACTIVE_LEVEL);
362 }
363 
365 {
366  return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed));
367 }
368 
370 {
371  return msg_level >= level_.load(std::memory_order_relaxed);
372 }
373 
374 //
375 // protected virtual called at end of each user log call (if enabled) by the
376 // line_logger
377 //
379 {
380 #if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
381  incr_msg_counter_(msg);
382 #endif
383  for (auto &sink : sinks_)
384  {
385  if (sink->should_log(msg.level))
386  {
387  sink->log(msg);
388  }
389  }
390 
391  if (should_flush_(msg))
392  {
393  flush_();
394  }
395 }
396 
398 {
399  for (auto &sink : sinks_)
400  {
401  sink->flush();
402  }
403 }
404 
405 inline void spdlog::logger::default_err_handler_(const std::string &msg)
406 {
407  auto now = time(nullptr);
408  if (now - last_err_time_ < 60)
409  {
410  return;
411  }
413  auto tm_time = details::os::localtime(now);
414  char date_buf[100];
415  std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
416  fmt::print(stderr, "[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, name(), msg);
417 }
418 
420 {
421  msg.msg_id = msg_counter_.fetch_add(1, std::memory_order_relaxed);
422 }
423 
424 inline const std::vector<spdlog::sink_ptr> &spdlog::logger::sinks() const
425 {
426  return sinks_;
427 }
428 
429 inline std::vector<spdlog::sink_ptr> &spdlog::logger::sinks()
430 {
431  return sinks_;
432 }
433 
434 inline std::shared_ptr<spdlog::logger> spdlog::logger::clone(std::string logger_name)
435 {
436  auto cloned = std::make_shared<spdlog::logger>(std::move(logger_name), sinks_.begin(), sinks_.end());
437  cloned->set_level(this->level());
438  cloned->flush_on(this->flush_level());
439  cloned->set_error_handler(this->error_handler());
440  return cloned;
441 }
level::level_enum flush_level() const
Definition: logger_impl.h:348
std::atomic< time_t > last_err_time_
Definition: logger.h:183
void incr_msg_counter_(details::log_msg &msg)
Definition: logger_impl.h:419
void log(level::level_enum lvl, const char *fmt, const Args &... args)
Definition: logger_impl.h:80
log_err_handler error_handler() const
Definition: logger_impl.h:329
basic_memory_buffer< char > memory_buffer
Definition: format.h:553
void trace(const char *fmt, const Args &... args)
Definition: logger_impl.h:151
std::initializer_list< sink_ptr > sinks_init_list
Definition: common.h:81
log_err_handler err_handler_
Definition: logger.h:182
spdlog::level_t level_
Definition: logger.h:180
FMT_CONSTEXPR auto begin(const C &c) -> decltype(c.begin())
Definition: format.h:251
std::atomic< size_t > msg_counter_
Definition: logger.h:184
const std::string & name() const
Definition: logger_impl.h:314
#define SPDLOG_CATCH_AND_HANDLE
Definition: logger_impl.h:13
If we are still before C++14, supply the fodder for doing the "indices trick".
Definition: format.h:297
level::level_enum level() const
Definition: logger_impl.h:364
void info(const char *fmt, const Args &... args)
Definition: logger_impl.h:163
void warn(const char *fmt, const Args &... args)
Definition: logger_impl.h:169
bool should_log(level::level_enum msg_level) const
Definition: logger_impl.h:369
std::shared_ptr< sinks::sink > sink_ptr
Definition: common.h:80
const std::string name_
Definition: logger.h:178
void debug(const char *fmt, const Args &... args)
Definition: logger_impl.h:157
const std::vector< sink_ptr > & sinks() const
Definition: logger_impl.h:424
void set_pattern(std::string pattern, pattern_time_type time_type=pattern_time_type::local)
Definition: logger_impl.h:54
static level::level_enum default_level()
Definition: logger_impl.h:359
std::vector< sink_ptr > sinks_
Definition: logger.h:179
std::basic_string< FMT_CHAR(S)> format(const S &format_str, const Args &... args)
Definition: core.h:1454
bool should_flush_(const details::log_msg &msg)
Definition: logger_impl.h:353
FMT_CONSTEXPR auto end(const C &c) -> decltype(c.end())
Definition: format.h:257
void critical(const char *fmt, const Args &... args)
Definition: logger_impl.h:181
level::level_enum level
Definition: log_msg.h:42
void error(const char *fmt, const Args &... args)
Definition: logger_impl.h:175
void default_err_handler_(const std::string &msg)
Definition: logger_impl.h:405
pattern_time_type
Definition: common.h:163
std::size_t strftime(char *str, std::size_t count, const char *format, const std::tm *time)
Definition: time.h:104
virtual ~logger()
spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT
Definition: os.h:60
virtual std::shared_ptr< logger > clone(std::string logger_name)
Definition: logger_impl.h:434
string_view_t & to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT
Definition: common.h:132
std::enable_if< is_contiguous< Container >::value &&internal::is_string< S >::value, std::back_insert_iterator< Container > >::type format_to(std::back_insert_iterator< Container > out, const S &format_str, const Args &... args)
Definition: core.h:1430
std::enable_if< internal::is_string< String >::value >::type print(std::FILE *f, const text_style &ts, const String &format_str, const Args &... args)
Definition: color.h:549
spdlog::level_t flush_level_
Definition: logger.h:181
fmt::string_view string_view_t
Definition: common.h:88
void set_formatter(std::unique_ptr< formatter > formatter)
Definition: logger_impl.h:46
virtual void flush_()
Definition: logger_impl.h:397
Definition: bin_to_hex.h:69
std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT
Definition: os.h:73
void set_error_handler(log_err_handler err_handler)
Definition: logger_impl.h:324
spdlog::string_view_t to_string_view(const fmt::basic_memory_buffer< char, Buffer_Size > &buf) SPDLOG_NOEXCEPT
Definition: fmt_helper.h:17
std::function< void(const std::string &err_msg)> log_err_handler
Definition: common.h:82
basic_memory_buffer< wchar_t > wmemory_buffer
Definition: format.h:554
logger(std::string name, sink_ptr single_sink)
Definition: logger_impl.h:39
#define SPDLOG_ACTIVE_LEVEL
Definition: common.h:106
const Args & args
Definition: core.h:1496
void set_level(level::level_enum log_level)
Definition: logger_impl.h:319
type
Definition: core.h:530
void flush_on(level::level_enum log_level)
Definition: logger_impl.h:343
virtual void sink_it_(details::log_msg &msg)
Definition: logger_impl.h:378