source: trunk/GDE/SINA/builddir/include/spdlog/details/logger_impl.h

Last change on this file was 19170, checked in by westram, 2 years ago
  • sina source
    • unpack + remove tarball
    • no longer ignore sina builddir.
File size: 11.5 KB
Line 
1//
2// Copyright(c) 2015 Gabi Melman.
3// Distributed under the MIT License (http://opensource.org/licenses/MIT)
4//
5
6#pragma once
7
8#include "spdlog/details/fmt_helper.h"
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
25template<typename It>
26inline 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
33inline 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
39inline 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
44inline spdlog::logger::~logger() = default;
45
46inline 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
54inline 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
60template<typename... Args>
61inline 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    {
70        using details::fmt_helper::to_string_view;
71        fmt::memory_buffer buf;
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    }
76    SPDLOG_CATCH_AND_HANDLE
77}
78
79template<typename... Args>
80inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Args &... args)
81{
82    log(source_loc{}, lvl, fmt, args...);
83}
84
85inline 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    }
97    SPDLOG_CATCH_AND_HANDLE
98}
99
100inline void spdlog::logger::log(level::level_enum lvl, const char *msg)
101{
102    log(source_loc{}, lvl, msg);
103}
104
105template<class T, typename std::enable_if<std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
106inline 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    }
117    SPDLOG_CATCH_AND_HANDLE
118}
119
120template<class T, typename std::enable_if<std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
121inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
122{
123    log(source_loc{}, lvl, msg);
124}
125
126template<class T, typename std::enable_if<!std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
127inline 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    {
135        using details::fmt_helper::to_string_view;
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    }
141    SPDLOG_CATCH_AND_HANDLE
142}
143
144template<class T, typename std::enable_if<!std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
145inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
146{
147    log(source_loc{}, lvl, msg);
148}
149
150template<typename... Args>
151inline void spdlog::logger::trace(const char *fmt, const Args &... args)
152{
153    log(level::trace, fmt, args...);
154}
155
156template<typename... Args>
157inline void spdlog::logger::debug(const char *fmt, const Args &... args)
158{
159    log(level::debug, fmt, args...);
160}
161
162template<typename... Args>
163inline void spdlog::logger::info(const char *fmt, const Args &... args)
164{
165    log(level::info, fmt, args...);
166}
167
168template<typename... Args>
169inline void spdlog::logger::warn(const char *fmt, const Args &... args)
170{
171    log(level::warn, fmt, args...);
172}
173
174template<typename... Args>
175inline void spdlog::logger::error(const char *fmt, const Args &... args)
176{
177    log(level::err, fmt, args...);
178}
179
180template<typename... Args>
181inline void spdlog::logger::critical(const char *fmt, const Args &... args)
182{
183    log(level::critical, fmt, args...);
184}
185
186template<typename T>
187inline void spdlog::logger::trace(const T &msg)
188{
189    log(level::trace, msg);
190}
191
192template<typename T>
193inline void spdlog::logger::debug(const T &msg)
194{
195    log(level::debug, msg);
196}
197
198template<typename T>
199inline void spdlog::logger::info(const T &msg)
200{
201    log(level::info, msg);
202}
203
204template<typename T>
205inline void spdlog::logger::warn(const T &msg)
206{
207    log(level::warn, msg);
208}
209
210template<typename T>
211inline void spdlog::logger::error(const T &msg)
212{
213    log(level::err, msg);
214}
215
216template<typename T>
217inline void spdlog::logger::critical(const T &msg)
218{
219    log(level::critical, msg);
220}
221
222#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
223
224inline 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
245template<typename... Args>
246inline 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
256        using details::fmt_helper::to_string_view;
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    }
264    SPDLOG_CATCH_AND_HANDLE
265}
266
267template<typename... Args>
268inline 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
273template<typename... Args>
274inline void spdlog::logger::trace(const wchar_t *fmt, const Args &... args)
275{
276    log(level::trace, fmt, args...);
277}
278
279template<typename... Args>
280inline void spdlog::logger::debug(const wchar_t *fmt, const Args &... args)
281{
282    log(level::debug, fmt, args...);
283}
284
285template<typename... Args>
286inline void spdlog::logger::info(const wchar_t *fmt, const Args &... args)
287{
288    log(level::info, fmt, args...);
289}
290
291template<typename... Args>
292inline void spdlog::logger::warn(const wchar_t *fmt, const Args &... args)
293{
294    log(level::warn, fmt, args...);
295}
296
297template<typename... Args>
298inline void spdlog::logger::error(const wchar_t *fmt, const Args &... args)
299{
300    log(level::err, fmt, args...);
301}
302
303template<typename... Args>
304inline 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//
314inline const std::string &spdlog::logger::name() const
315{
316    return name_;
317}
318
319inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
320{
321    level_.store(log_level);
322}
323
324inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler)
325{
326    err_handler_ = std::move(err_handler);
327}
328
329inline spdlog::log_err_handler spdlog::logger::error_handler() const
330{
331    return err_handler_;
332}
333
334inline void spdlog::logger::flush()
335{
336    try
337    {
338        flush_();
339    }
340    SPDLOG_CATCH_AND_HANDLE
341}
342
343inline void spdlog::logger::flush_on(level::level_enum log_level)
344{
345    flush_level_.store(log_level);
346}
347
348inline spdlog::level::level_enum spdlog::logger::flush_level() const
349{
350    return static_cast<spdlog::level::level_enum>(flush_level_.load(std::memory_order_relaxed));
351}
352
353inline bool spdlog::logger::should_flush_(const details::log_msg &msg)
354{
355    auto flush_level = flush_level_.load(std::memory_order_relaxed);
356    return (msg.level >= flush_level) && (msg.level != level::off);
357}
358
359inline spdlog::level::level_enum spdlog::logger::default_level()
360{
361    return static_cast<spdlog::level::level_enum>(SPDLOG_ACTIVE_LEVEL);
362}
363
364inline spdlog::level::level_enum spdlog::logger::level() const
365{
366    return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed));
367}
368
369inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const
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//
378inline void spdlog::logger::sink_it_(details::log_msg &msg)
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
397inline void spdlog::logger::flush_()
398{
399    for (auto &sink : sinks_)
400    {
401        sink->flush();
402    }
403}
404
405inline 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    }
412    last_err_time_ = now;
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
419inline void spdlog::logger::incr_msg_counter_(details::log_msg &msg)
420{
421    msg.msg_id = msg_counter_.fetch_add(1, std::memory_order_relaxed);
422}
423
424inline const std::vector<spdlog::sink_ptr> &spdlog::logger::sinks() const
425{
426    return sinks_;
427}
428
429inline std::vector<spdlog::sink_ptr> &spdlog::logger::sinks()
430{
431    return sinks_;
432}
433
434inline 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}
Note: See TracBrowser for help on using the repository browser.