static lib wip
This commit is contained in:
		
							parent
							
								
									ef8773a89b
								
							
						
					
					
						commit
						e2e3df9013
					
				| @ -10,16 +10,15 @@ | ||||
| #include "spdlog/logger.h" | ||||
| 
 | ||||
| 
 | ||||
| namespace spdlog { | ||||
| class logger; | ||||
| } | ||||
| 
 | ||||
| spdlog::logger *get_logger(); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int main(int, char *[]) | ||||
| {     | ||||
|     auto *l = get_logger(); | ||||
|     l->info("HELLO"); | ||||
|     l->info("HELLO  {}", "World");     | ||||
| 	l->warn("SOME WARNINNG"); | ||||
|     l->error("Some {}", "error"); | ||||
|     | ||||
| 
 | ||||
| } | ||||
| @ -27,6 +27,13 @@ | ||||
| 
 | ||||
| #include "spdlog/fmt/fmt.h" | ||||
| 
 | ||||
| #ifdef SPDLOG_HEADER_ONLY | ||||
| #define SPDLOG_INLINE inline | ||||
| #else | ||||
| #define SPDLOG_INLINE | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| // visual studio upto 2013 does not support noexcept nor constexpr
 | ||||
| #if defined(_MSC_VER) && (_MSC_VER < 1900) | ||||
| #define SPDLOG_NOEXCEPT throw() | ||||
|  | ||||
| @ -79,7 +79,14 @@ inline void spdlog::async_logger::backend_log_(const details::log_msg &incoming_ | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     SPDLOG_CATCH_AND_HANDLE | ||||
|     catch (const std::exception &ex) | ||||
|     { | ||||
|         err_handler_(ex.what()); | ||||
|     } | ||||
|     catch (...) | ||||
|     { | ||||
|         err_handler_("Unknown exception in logger"); | ||||
|     } | ||||
| 
 | ||||
|     if (should_flush_(incoming_log_msg)) | ||||
|     { | ||||
| @ -96,7 +103,14 @@ inline void spdlog::async_logger::backend_flush_() | ||||
|             sink->flush(); | ||||
|         } | ||||
|     } | ||||
|     SPDLOG_CATCH_AND_HANDLE | ||||
|     catch (const std::exception &ex) | ||||
|     { | ||||
|         err_handler_(ex.what()); | ||||
|     } | ||||
|     catch (...) | ||||
|     { | ||||
|         err_handler_("Unknown exception in logger"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| inline std::shared_ptr<spdlog::logger> spdlog::async_logger::clone(std::string new_name) | ||||
|  | ||||
| @ -7,6 +7,7 @@ | ||||
| #include <chrono> | ||||
| #include <type_traits> | ||||
| #include "spdlog/fmt/fmt.h" | ||||
| #include "spdlog/common.h" | ||||
| 
 | ||||
| // Some fmt helpers to efficiently format and pad ints and strings
 | ||||
| namespace spdlog { | ||||
|  | ||||
| @ -6,36 +6,16 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "spdlog/common.h" | ||||
| #include "spdlog/details/os.h" | ||||
| 
 | ||||
| #include <string> | ||||
| #include <utility> | ||||
| 
 | ||||
| namespace spdlog { | ||||
| namespace details { | ||||
| struct log_msg | ||||
| { | ||||
| 
 | ||||
|     log_msg(source_loc loc, const std::string *loggers_name, level::level_enum lvl, string_view_t view) | ||||
|         : logger_name(loggers_name) | ||||
|         , level(lvl) | ||||
| #ifndef SPDLOG_NO_DATETIME | ||||
|         , time(os::now()) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef SPDLOG_NO_THREAD_ID | ||||
|         , thread_id(os::thread_id()) | ||||
| #endif | ||||
|         , source(loc) | ||||
|         , payload(view) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     log_msg(const std::string *loggers_name, level::level_enum lvl, string_view_t view) | ||||
|         : log_msg(source_loc{}, loggers_name, lvl, view) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     log_msg(source_loc loc, const std::string *loggers_name, level::level_enum lvl, string_view_t view); | ||||
|         | ||||
|     log_msg(const std::string *loggers_name, level::level_enum lvl, string_view_t view); | ||||
|     log_msg(const log_msg &other) = default; | ||||
| 
 | ||||
|     const std::string *logger_name{nullptr}; | ||||
|  | ||||
| @ -1,435 +0,0 @@ | ||||
| //
 | ||||
| // Copyright(c) 2015 Gabi Melman.
 | ||||
| // Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | ||||
| //
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "spdlog/details/fmt_helper.h" | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <string> | ||||
| 
 | ||||
| //#define SPDLOG_CATCH_AND_HANDLE                                                                                                            \ | ||||
| //    catch (const std::exception &ex)                                                                                                       \ | ||||
| //    {                                                                                                                                      \ | ||||
| //        err_handler_(ex.what());                                                                                                           \ | ||||
| //    }                                                                                                                                      \ | ||||
| //    catch (...)                                                                                                                            \ | ||||
| //    {                                                                                                                                      \ | ||||
| //        err_handler_("Unknown exception in logger");                                                                                       \ | ||||
| //    }
 | ||||
| 
 | ||||
| // create logger with given name, sinks and the default pattern formatter
 | ||||
| // all other ctors will call this one
 | ||||
| //template<typename It>
 | ||||
| //inline spdlog::logger::logger(std::string logger_name, It begin, It end)
 | ||||
| //    : name_(std::move(logger_name))
 | ||||
| //    , sinks_(begin, end)
 | ||||
| //{
 | ||||
| //}
 | ||||
| 
 | ||||
| //// ctor with sinks as init list
 | ||||
| //inline spdlog::logger::logger(std::string logger_name, sinks_init_list sinks_list)
 | ||||
| //    : logger(std::move(logger_name), sinks_list.begin(), sinks_list.end())
 | ||||
| //{
 | ||||
| //}
 | ||||
| 
 | ||||
| // ctor with single sink
 | ||||
| //inline spdlog::logger::logger(std::string logger_name, spdlog::sink_ptr single_sink)
 | ||||
| //    : logger(std::move(logger_name), {std::move(single_sink)})
 | ||||
| //{
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline spdlog::logger::~logger() = default;
 | ||||
| 
 | ||||
| //inline void spdlog::logger::set_formatter(std::unique_ptr<spdlog::formatter> f)
 | ||||
| //{
 | ||||
| //    for (auto &sink : sinks_)
 | ||||
| //    {
 | ||||
| //        sink->set_formatter(f->clone());
 | ||||
| //    }
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline void spdlog::logger::set_pattern(std::string pattern, pattern_time_type time_type)
 | ||||
| //{
 | ||||
| //    auto new_formatter = details::make_unique<spdlog::pattern_formatter>(std::move(pattern), time_type);
 | ||||
| //    set_formatter(std::move(new_formatter));
 | ||||
| //}
 | ||||
| 
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const char *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    if (!should_log(lvl))
 | ||||
| //    {
 | ||||
| //        return;
 | ||||
| //    }
 | ||||
| //
 | ||||
| //    try
 | ||||
| //    {
 | ||||
| //        using details::fmt_helper::to_string_view;
 | ||||
| //        fmt::memory_buffer buf;
 | ||||
| //        fmt::format_to(buf, fmt, args...);
 | ||||
| //        details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
 | ||||
| //        sink_it_(log_msg);
 | ||||
| //    }
 | ||||
| //    SPDLOG_CATCH_AND_HANDLE
 | ||||
| //}
 | ||||
| 
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(source_loc{}, lvl, fmt, args...);
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const char *msg)
 | ||||
| //{
 | ||||
| //    if (!should_log(lvl))
 | ||||
| //    {
 | ||||
| //        return;
 | ||||
| //    }
 | ||||
| //
 | ||||
| //    try
 | ||||
| //    {
 | ||||
| //        details::log_msg log_msg(source, &name_, lvl, spdlog::string_view_t(msg));
 | ||||
| //        sink_it_(log_msg);
 | ||||
| //    }
 | ||||
| //    SPDLOG_CATCH_AND_HANDLE
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline void spdlog::logger::log(level::level_enum lvl, const char *msg)
 | ||||
| //{
 | ||||
| //    log(source_loc{}, lvl, msg);
 | ||||
| //}
 | ||||
| 
 | ||||
| //template<class T>
 | ||||
| //inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
 | ||||
| //{
 | ||||
| //    log(source_loc{}, lvl, msg);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<class T, typename std::enable_if<std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
 | ||||
| //inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const T &msg)
 | ||||
| //{
 | ||||
| //    if (!should_log(lvl))
 | ||||
| //    {
 | ||||
| //        return;
 | ||||
| //    }
 | ||||
| //    try
 | ||||
| //    {
 | ||||
| //        details::log_msg log_msg(source, &name_, lvl, msg);
 | ||||
| //        sink_it_(log_msg);
 | ||||
| //    }
 | ||||
| //    SPDLOG_CATCH_AND_HANDLE
 | ||||
| //}
 | ||||
| 
 | ||||
| //template<class T, typename std::enable_if<!std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
 | ||||
| //inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const T &msg)
 | ||||
| //{
 | ||||
| //    if (!should_log(lvl))
 | ||||
| //    {
 | ||||
| //        return;
 | ||||
| //    }
 | ||||
| //    try
 | ||||
| //    {
 | ||||
| //        using details::fmt_helper::to_string_view;
 | ||||
| //        fmt::memory_buffer buf;
 | ||||
| //        fmt::format_to(buf, "{}", msg);
 | ||||
| //        details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
 | ||||
| //        sink_it_(log_msg);
 | ||||
| //    }
 | ||||
| //    SPDLOG_CATCH_AND_HANDLE
 | ||||
| //}
 | ||||
| 
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::trace(const char *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::trace, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::debug(const char *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::debug, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::info(const char *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::info, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::warn(const char *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::warn, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::error(const char *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::err, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::critical(const char *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::critical, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename T>
 | ||||
| //inline void spdlog::logger::trace(const T &msg)
 | ||||
| //{
 | ||||
| //    log(level::trace, msg);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename T>
 | ||||
| //inline void spdlog::logger::debug(const T &msg)
 | ||||
| //{
 | ||||
| //    log(level::debug, msg);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename T>
 | ||||
| //inline void spdlog::logger::info(const T &msg)
 | ||||
| //{
 | ||||
| //    log(level::info, msg);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename T>
 | ||||
| //inline void spdlog::logger::warn(const T &msg)
 | ||||
| //{
 | ||||
| //    log(level::warn, msg);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename T>
 | ||||
| //inline void spdlog::logger::error(const T &msg)
 | ||||
| //{
 | ||||
| //    log(level::err, msg);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename T>
 | ||||
| //inline void spdlog::logger::critical(const T &msg)
 | ||||
| //{
 | ||||
| //    log(level::critical, msg);
 | ||||
| //}
 | ||||
| 
 | ||||
| //#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
 | ||||
| 
 | ||||
| //inline void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target)
 | ||||
| //{
 | ||||
| //    int wbuf_size = static_cast<int>(wbuf.size());
 | ||||
| //    if (wbuf_size == 0)
 | ||||
| //    {
 | ||||
| //        return;
 | ||||
| //    }
 | ||||
| //
 | ||||
| //    auto result_size = ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, NULL, 0, NULL, NULL);
 | ||||
| //
 | ||||
| //    if (result_size > 0)
 | ||||
| //    {
 | ||||
| //        target.resize(result_size);
 | ||||
| //        ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, &target.data()[0], result_size, NULL, NULL);
 | ||||
| //    }
 | ||||
| //    else
 | ||||
| //    {
 | ||||
| //        throw spdlog::spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError()));
 | ||||
| //    }
 | ||||
| //}
 | ||||
| 
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    if (!should_log(lvl))
 | ||||
| //    {
 | ||||
| //        return;
 | ||||
| //    }
 | ||||
| //
 | ||||
| //    try
 | ||||
| //    {
 | ||||
| //        // format to wmemory_buffer and convert to utf8
 | ||||
| //        using details::fmt_helper::to_string_view;
 | ||||
| //        fmt::wmemory_buffer wbuf;
 | ||||
| //        fmt::format_to(wbuf, fmt, args...);
 | ||||
| //        fmt::memory_buffer buf;
 | ||||
| //        wbuf_to_utf8buf(wbuf, buf);
 | ||||
| //        details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
 | ||||
| //        sink_it_(log_msg);
 | ||||
| //    }
 | ||||
| //    SPDLOG_CATCH_AND_HANDLE
 | ||||
| //}
 | ||||
| 
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::log(level::level_enum lvl, const wchar_t *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(source_loc{}, lvl, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::trace(const wchar_t *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::trace, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::debug(const wchar_t *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::debug, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::info(const wchar_t *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::info, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::warn(const wchar_t *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::warn, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::error(const wchar_t *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::err, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //template<typename... Args>
 | ||||
| //inline void spdlog::logger::critical(const wchar_t *fmt, const Args &... args)
 | ||||
| //{
 | ||||
| //    log(level::critical, fmt, args...);
 | ||||
| //}
 | ||||
| //
 | ||||
| //#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
 | ||||
| 
 | ||||
| //
 | ||||
| // name and level
 | ||||
| //
 | ||||
| //inline const std::string &spdlog::logger::name() const
 | ||||
| //{
 | ||||
| //    return name_;
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
 | ||||
| //{
 | ||||
| //    level_.store(log_level);
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler)
 | ||||
| //{
 | ||||
| //    err_handler_ = std::move(err_handler);
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline spdlog::log_err_handler spdlog::logger::error_handler() const
 | ||||
| //{
 | ||||
| //    return err_handler_;
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline void spdlog::logger::flush()
 | ||||
| //{
 | ||||
| //    try
 | ||||
| //    {
 | ||||
| //        flush_();
 | ||||
| //    }
 | ||||
| //    SPDLOG_CATCH_AND_HANDLE
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline void spdlog::logger::flush_on(level::level_enum log_level)
 | ||||
| //{
 | ||||
| //    flush_level_.store(log_level);
 | ||||
| //}
 | ||||
| //
 | ||||
| //inline spdlog::level::level_enum spdlog::logger::flush_level() const
 | ||||
| //{
 | ||||
| //    return static_cast<spdlog::level::level_enum>(flush_level_.load(std::memory_order_relaxed));
 | ||||
| //}
 | ||||
| //
 | ||||
| //inline bool spdlog::logger::should_flush_(const details::log_msg &msg)
 | ||||
| //{
 | ||||
| //    auto flush_level = flush_level_.load(std::memory_order_relaxed);
 | ||||
| //    return (msg.level >= flush_level) && (msg.level != level::off);
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline spdlog::level::level_enum spdlog::logger::default_level()
 | ||||
| //{
 | ||||
| //    return static_cast<spdlog::level::level_enum>(SPDLOG_ACTIVE_LEVEL);
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline spdlog::level::level_enum spdlog::logger::level() const
 | ||||
| //{
 | ||||
| //    return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed));
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const
 | ||||
| //{
 | ||||
| //    return msg_level >= level_.load(std::memory_order_relaxed);
 | ||||
| //}
 | ||||
| 
 | ||||
| //
 | ||||
| // protected virtual called at end of each user log call (if enabled) by the
 | ||||
| // line_logger
 | ||||
| //
 | ||||
| //inline void spdlog::logger::sink_it_(details::log_msg &msg)
 | ||||
| //{
 | ||||
| //#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
 | ||||
| //    incr_msg_counter_(msg);
 | ||||
| //#endif
 | ||||
| //    for (auto &sink : sinks_)
 | ||||
| //    {
 | ||||
| //        if (sink->should_log(msg.level))
 | ||||
| //        {
 | ||||
| //            sink->log(msg);
 | ||||
| //        }
 | ||||
| //    }
 | ||||
| //
 | ||||
| //    if (should_flush_(msg))
 | ||||
| //    {
 | ||||
| //        flush_();
 | ||||
| //    }
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline void spdlog::logger::flush_()
 | ||||
| //{
 | ||||
| //    for (auto &sink : sinks_)
 | ||||
| //    {
 | ||||
| //        sink->flush();
 | ||||
| //    }
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline void spdlog::logger::default_err_handler_(const std::string &msg)
 | ||||
| //{
 | ||||
| //    auto now = time(nullptr);
 | ||||
| //    if (now - last_err_time_ < 60)
 | ||||
| //    {
 | ||||
| //        return;
 | ||||
| //    }
 | ||||
| //    last_err_time_ = now;
 | ||||
| //    auto tm_time = details::os::localtime(now);
 | ||||
| //    char date_buf[100];
 | ||||
| //    std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
 | ||||
| //    fmt::print(stderr, "[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, name(), msg);
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline void spdlog::logger::incr_msg_counter_(details::log_msg &msg)
 | ||||
| //{
 | ||||
| //    msg.msg_id = msg_counter_.fetch_add(1, std::memory_order_relaxed);
 | ||||
| //}
 | ||||
| //
 | ||||
| //inline const std::vector<spdlog::sink_ptr> &spdlog::logger::sinks() const
 | ||||
| //{
 | ||||
| //    return sinks_;
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline std::vector<spdlog::sink_ptr> &spdlog::logger::sinks()
 | ||||
| //{
 | ||||
| //    return sinks_;
 | ||||
| //}
 | ||||
| 
 | ||||
| //inline std::shared_ptr<spdlog::logger> spdlog::logger::clone(std::string logger_name)
 | ||||
| //{
 | ||||
| //    auto cloned = std::make_shared<spdlog::logger>(std::move(logger_name), sinks_.begin(), sinks_.end());
 | ||||
| //    cloned->set_level(this->level());
 | ||||
| //    cloned->flush_on(this->flush_level());
 | ||||
| //    cloned->set_error_handler(this->error_handler());
 | ||||
| //    return cloned;
 | ||||
| //}
 | ||||
| @ -18,95 +18,19 @@ | ||||
| #include <sys/types.h> | ||||
| #include <thread> | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| 
 | ||||
| #ifndef NOMINMAX | ||||
| #define NOMINMAX // prevent windows redefining min/max
 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef WIN32_LEAN_AND_MEAN | ||||
| #define WIN32_LEAN_AND_MEAN | ||||
| #endif | ||||
| #include <io.h>      // _get_osfhandle and _isatty support | ||||
| #include <process.h> //  _get_pid support | ||||
| #include <windows.h> | ||||
| 
 | ||||
| #ifdef __MINGW32__ | ||||
| #include <share.h> | ||||
| #endif | ||||
| 
 | ||||
| #else // unix
 | ||||
| 
 | ||||
| #include <fcntl.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #ifdef __linux__ | ||||
| #include <sys/syscall.h> //Use gettid() syscall under linux to get thread id | ||||
| 
 | ||||
| #elif __FreeBSD__ | ||||
| #include <sys/thr.h> //Use thr_self() syscall under FreeBSD to get thread id | ||||
| #endif | ||||
| 
 | ||||
| #endif // unix
 | ||||
| 
 | ||||
| #ifndef __has_feature      // Clang - feature checking macros.
 | ||||
| #define __has_feature(x) 0 // Compatibility with non-clang compilers.
 | ||||
| #endif | ||||
| 
 | ||||
| namespace spdlog { | ||||
| namespace details { | ||||
| namespace os { | ||||
| 
 | ||||
| inline spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT | ||||
| { | ||||
| spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| #if defined __linux__ && defined SPDLOG_CLOCK_COARSE | ||||
|     timespec ts; | ||||
|     ::clock_gettime(CLOCK_REALTIME_COARSE, &ts); | ||||
|     return std::chrono::time_point<log_clock, typename log_clock::duration>( | ||||
|         std::chrono::duration_cast<typename log_clock::duration>(std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec))); | ||||
| std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| #else | ||||
|     return log_clock::now(); | ||||
| #endif | ||||
| } | ||||
| inline std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT | ||||
| { | ||||
| std::tm localtime() SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     std::tm tm; | ||||
|     localtime_s(&tm, &time_tt); | ||||
| #else | ||||
|     std::tm tm; | ||||
|     localtime_r(&time_tt, &tm); | ||||
| #endif | ||||
|     return tm; | ||||
| } | ||||
| std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| inline std::tm localtime() SPDLOG_NOEXCEPT | ||||
| { | ||||
|     std::time_t now_t = time(nullptr); | ||||
|     return localtime(now_t); | ||||
| } | ||||
| 
 | ||||
| inline std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     std::tm tm; | ||||
|     gmtime_s(&tm, &time_tt); | ||||
| #else | ||||
|     std::tm tm; | ||||
|     gmtime_r(&time_tt, &tm); | ||||
| #endif | ||||
|     return tm; | ||||
| } | ||||
| 
 | ||||
| inline std::tm gmtime() SPDLOG_NOEXCEPT | ||||
| { | ||||
|     std::time_t now_t = time(nullptr); | ||||
|     return gmtime(now_t); | ||||
| } | ||||
| std::tm gmtime() SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| // eol definition
 | ||||
| #if !defined(SPDLOG_EOL) | ||||
| @ -121,301 +45,56 @@ SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL; | ||||
| 
 | ||||
| // folder separator
 | ||||
| #ifdef _WIN32 | ||||
| SPDLOG_CONSTEXPR static const char folder_sep = '\\'; | ||||
| const char folder_sep = '\\'; | ||||
| #else | ||||
| SPDLOG_CONSTEXPR static const char folder_sep = '/'; | ||||
| #endif | ||||
| 
 | ||||
| inline void prevent_child_fd(FILE *f) | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #if !defined(__cplusplus_winrt) | ||||
|     auto file_handle = (HANDLE)_get_osfhandle(_fileno(f)); | ||||
|     if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)) | ||||
|         throw spdlog_ex("SetHandleInformation failed", errno); | ||||
| #endif | ||||
| #else | ||||
|     auto fd = fileno(f); | ||||
|     if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) | ||||
|     { | ||||
|         throw spdlog_ex("fcntl with FD_CLOEXEC failed", errno); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| void prevent_child_fd(FILE *f); | ||||
| 
 | ||||
| // fopen_s on non windows for writing
 | ||||
| inline bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) | ||||
| { | ||||
| #ifdef _WIN32 | ||||
| #ifdef SPDLOG_WCHAR_FILENAMES | ||||
|     *fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); | ||||
| #else | ||||
|     *fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); | ||||
| #endif | ||||
| #else // unix
 | ||||
|     *fp = fopen((filename.c_str()), mode.c_str()); | ||||
| #endif | ||||
| bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode); | ||||
| 
 | ||||
| #ifdef SPDLOG_PREVENT_CHILD_FD | ||||
|     if (*fp != nullptr) | ||||
|     { | ||||
|         prevent_child_fd(*fp); | ||||
|     } | ||||
| #endif | ||||
|     return *fp == nullptr; | ||||
| } | ||||
| int remove(const filename_t &filename) SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| inline int remove(const filename_t &filename) SPDLOG_NOEXCEPT | ||||
| { | ||||
| #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) | ||||
|     return _wremove(filename.c_str()); | ||||
| #else | ||||
|     return std::remove(filename.c_str()); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| inline int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT | ||||
| { | ||||
| #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) | ||||
|     return _wrename(filename1.c_str(), filename2.c_str()); | ||||
| #else | ||||
|     return std::rename(filename1.c_str(), filename2.c_str()); | ||||
| #endif | ||||
| } | ||||
| int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| // Return if file exists
 | ||||
| inline bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT | ||||
| { | ||||
| #ifdef _WIN32 | ||||
| #ifdef SPDLOG_WCHAR_FILENAMES | ||||
|     auto attribs = GetFileAttributesW(filename.c_str()); | ||||
| #else | ||||
|     auto attribs = GetFileAttributesA(filename.c_str()); | ||||
| #endif | ||||
|     return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY)); | ||||
| #else // common linux/unix all have the stat system call
 | ||||
|     struct stat buffer; | ||||
|     return (stat(filename.c_str(), &buffer) == 0); | ||||
| #endif | ||||
| } | ||||
| bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| // Return file size according to open FILE* object
 | ||||
| inline size_t filesize(FILE *f) | ||||
| { | ||||
|     if (f == nullptr) | ||||
|     { | ||||
|         throw spdlog_ex("Failed getting file size. fd is null"); | ||||
|     } | ||||
| #if defined(_WIN32) && !defined(__CYGWIN__) | ||||
|     int fd = _fileno(f); | ||||
| #if _WIN64 // 64 bits
 | ||||
|     __int64 ret = _filelengthi64(fd); | ||||
|     if (ret >= 0) | ||||
|     { | ||||
|         return static_cast<size_t>(ret); | ||||
|     } | ||||
| 
 | ||||
| #else // windows 32 bits
 | ||||
|     long ret = _filelength(fd); | ||||
|     if (ret >= 0) | ||||
|     { | ||||
|         return static_cast<size_t>(ret); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
| #else // unix
 | ||||
|     int fd = fileno(f); | ||||
| // 64 bits(but not in osx or cygwin, where fstat64 is deprecated)
 | ||||
| #if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) && !defined(__CYGWIN__) | ||||
|     struct stat64 st; | ||||
|     if (fstat64(fd, &st) == 0) | ||||
|     { | ||||
|         return static_cast<size_t>(st.st_size); | ||||
|     } | ||||
| #else // unix 32 bits or cygwin
 | ||||
|     struct stat st; | ||||
| 
 | ||||
|     if (fstat(fd, &st) == 0) | ||||
|     { | ||||
|         return static_cast<size_t>(st.st_size); | ||||
|     } | ||||
| #endif | ||||
| #endif | ||||
|     throw spdlog_ex("Failed getting file size from fd", errno); | ||||
| } | ||||
| size_t filesize(FILE *f); | ||||
| 
 | ||||
| // Return utc offset in minutes or throw spdlog_ex on failure
 | ||||
| inline int utc_minutes_offset(const std::tm &tm = details::os::localtime()) | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #if _WIN32_WINNT < _WIN32_WINNT_WS08 | ||||
|     TIME_ZONE_INFORMATION tzinfo; | ||||
|     auto rv = GetTimeZoneInformation(&tzinfo); | ||||
| #else | ||||
|     DYNAMIC_TIME_ZONE_INFORMATION tzinfo; | ||||
|     auto rv = GetDynamicTimeZoneInformation(&tzinfo); | ||||
| #endif | ||||
|     if (rv == TIME_ZONE_ID_INVALID) | ||||
|         throw spdlog::spdlog_ex("Failed getting timezone info. ", errno); | ||||
| 
 | ||||
|     int offset = -tzinfo.Bias; | ||||
|     if (tm.tm_isdst) | ||||
|     { | ||||
|         offset -= tzinfo.DaylightBias; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         offset -= tzinfo.StandardBias; | ||||
|     } | ||||
|     return offset; | ||||
| #else | ||||
| 
 | ||||
| #if defined(sun) || defined(__sun) || defined(_AIX) | ||||
|     // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
 | ||||
|     struct helper | ||||
|     { | ||||
|         static long int calculate_gmt_offset(const std::tm &localtm = details::os::localtime(), const std::tm &gmtm = details::os::gmtime()) | ||||
|         { | ||||
|             int local_year = localtm.tm_year + (1900 - 1); | ||||
|             int gmt_year = gmtm.tm_year + (1900 - 1); | ||||
| 
 | ||||
|             long int days = ( | ||||
|                 // difference in day of year
 | ||||
|                 localtm.tm_yday - | ||||
|                 gmtm.tm_yday | ||||
| 
 | ||||
|                 // + intervening leap days
 | ||||
|                 + ((local_year >> 2) - (gmt_year >> 2)) - (local_year / 100 - gmt_year / 100) + | ||||
|                 ((local_year / 100 >> 2) - (gmt_year / 100 >> 2)) | ||||
| 
 | ||||
|                 // + difference in years * 365 */
 | ||||
|                 + (long int)(local_year - gmt_year) * 365); | ||||
| 
 | ||||
|             long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour); | ||||
|             long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min); | ||||
|             long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec); | ||||
| 
 | ||||
|             return secs; | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     auto offset_seconds = helper::calculate_gmt_offset(tm); | ||||
| #else | ||||
|     auto offset_seconds = tm.tm_gmtoff; | ||||
| #endif | ||||
| 
 | ||||
|     return static_cast<int>(offset_seconds / 60); | ||||
| #endif | ||||
| } | ||||
| int utc_minutes_offset(const std::tm &tm = details::os::localtime()); | ||||
| 
 | ||||
| // Return current thread id as size_t
 | ||||
| // It exists because the std::this_thread::get_id() is much slower(especially
 | ||||
| // under VS 2013)
 | ||||
| inline size_t _thread_id() SPDLOG_NOEXCEPT | ||||
| { | ||||
| #ifdef _WIN32 | ||||
|     return static_cast<size_t>(::GetCurrentThreadId()); | ||||
| #elif __linux__ | ||||
| #if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) | ||||
| #define SYS_gettid __NR_gettid | ||||
| #endif | ||||
|     return static_cast<size_t>(syscall(SYS_gettid)); | ||||
| #elif __FreeBSD__ | ||||
|     long tid; | ||||
|     thr_self(&tid); | ||||
|     return static_cast<size_t>(tid); | ||||
| #elif __APPLE__ | ||||
|     uint64_t tid; | ||||
|     pthread_threadid_np(nullptr, &tid); | ||||
|     return static_cast<size_t>(tid); | ||||
| #else // Default to standard C++11 (other Unix)
 | ||||
|     return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id())); | ||||
| #endif | ||||
| } | ||||
| size_t _thread_id() SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| // Return current thread id as size_t (from thread local storage)
 | ||||
| inline size_t thread_id() SPDLOG_NOEXCEPT | ||||
| { | ||||
| #if defined(SPDLOG_NO_TLS) | ||||
|     return _thread_id(); | ||||
| #else // cache thread id in tls
 | ||||
|     static thread_local const size_t tid = _thread_id(); | ||||
|     return tid; | ||||
| #endif | ||||
| } | ||||
| size_t thread_id() SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| // This is avoid msvc issue in sleep_for that happens if the clock changes.
 | ||||
| // See https://github.com/gabime/spdlog/issues/609
 | ||||
| inline void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT | ||||
| { | ||||
| #if defined(_WIN32) | ||||
|     ::Sleep(milliseconds); | ||||
| #else | ||||
|     std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); | ||||
| #endif | ||||
| } | ||||
| void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| // wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
 | ||||
| #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) | ||||
| #define SPDLOG_FILENAME_T(s) L##s | ||||
| inline std::string filename_to_str(const filename_t &filename) | ||||
| { | ||||
|     std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> c; | ||||
|     return c.to_bytes(filename); | ||||
| } | ||||
| #else | ||||
| #define SPDLOG_FILENAME_T(s) s | ||||
| inline std::string filename_to_str(const filename_t &filename) | ||||
| { | ||||
|     return filename; | ||||
| } | ||||
| #endif | ||||
| std::string filename_to_str(const filename_t &filename); | ||||
| 
 | ||||
| inline int pid() | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     return static_cast<int>(::GetCurrentProcessId()); | ||||
| #else | ||||
|     return static_cast<int>(::getpid()); | ||||
| #endif | ||||
| } | ||||
| int pid(); | ||||
| 
 | ||||
| // Determine if the terminal supports colors
 | ||||
| // Source: https://github.com/agauniyal/rang/
 | ||||
| inline bool is_color_terminal() SPDLOG_NOEXCEPT | ||||
| { | ||||
| #ifdef _WIN32 | ||||
|     return true; | ||||
| #else | ||||
|     static constexpr const char *Terms[] = { | ||||
|         "ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", "linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm"}; | ||||
| 
 | ||||
|     const char *env_p = std::getenv("TERM"); | ||||
|     if (env_p == nullptr) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     static const bool result = | ||||
|         std::any_of(std::begin(Terms), std::end(Terms), [&](const char *term) { return std::strstr(env_p, term) != nullptr; }); | ||||
|     return result; | ||||
| #endif | ||||
| } | ||||
| bool is_color_terminal() SPDLOG_NOEXCEPT; | ||||
| 
 | ||||
| // Detrmine if the terminal attached
 | ||||
| // Source: https://github.com/agauniyal/rang/
 | ||||
| inline bool in_terminal(FILE *file) SPDLOG_NOEXCEPT | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     return _isatty(_fileno(file)) != 0; | ||||
| #else | ||||
|     return isatty(fileno(file)) != 0; | ||||
| #endif | ||||
| } | ||||
| bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; | ||||
| } // namespace os
 | ||||
| } // namespace details
 | ||||
| } // namespace spdlog
 | ||||
| 
 | ||||
| #ifdef SPDLOG_HEADER_ONLY | ||||
| #include "../src/os.cpp" | ||||
| #endif | ||||
|  | ||||
| @ -4,7 +4,6 @@ | ||||
| //
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "spdlog/details/fmt_helper.h" | ||||
| #include "spdlog/details/log_msg.h" | ||||
| #include "spdlog/details/os.h" | ||||
|  | ||||
| @ -13,6 +13,7 @@ | ||||
| #include "spdlog/common.h" | ||||
| #include "spdlog/details/periodic_worker.h" | ||||
| #include "spdlog/logger.h" | ||||
| #include "spdlog/details/pattern_formatter.h" | ||||
| 
 | ||||
| #ifndef SPDLOG_DISABLE_DEFAULT_LOGGER | ||||
| // support for the default stdout color logger
 | ||||
|  | ||||
| @ -15,469 +15,353 @@ | ||||
| // and send to its destination.
 | ||||
| //
 | ||||
| // The use of private formatter per sink provides the opportunity to cache some
 | ||||
| // formatted data,
 | ||||
| // and support customize format per each sink.
 | ||||
| // formatted data, and support for different format per sink.
 | ||||
| 
 | ||||
| 
 | ||||
| #include "spdlog/common.h" | ||||
| #include "spdlog/formatter.h" | ||||
| #include "spdlog/sinks/sink.h" | ||||
| #include "spdlog/details/fmt_helper.h" | ||||
| #include "spdlog/details/log_msg.h" | ||||
| 
 | ||||
| //#include "spdlog/formatter.h"
 | ||||
| //#include "spdlog/sinks/sink.h"
 | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| #ifndef SPDLOG_CATCH_AND_HANDLE | ||||
| 
 | ||||
| #define SPDLOG_CATCH_AND_HANDLE                                                                                                            \ | ||||
|     catch (const std::exception &ex)                                                                                                       \ | ||||
|     {                                                                                                                                      \ | ||||
|         err_handler_(ex.what());                                                                                                           \ | ||||
|     }                                                                                                                                      \ | ||||
|     catch (...)                                                                                                                            \ | ||||
|     {                                                                                                                                      \ | ||||
|         err_handler_("Unknown exception in logger");                                                                                       \ | ||||
|     } | ||||
| 
 | ||||
| #endif // ! SPDLOG_CATCH_AND_HANDLE
 | ||||
| 
 | ||||
| 
 | ||||
| namespace spdlog { | ||||
| 
 | ||||
| class logger | ||||
| namespace spdlog | ||||
| { | ||||
| public: | ||||
|      | ||||
|     template<typename It> | ||||
|     logger(std::string name, It begin, It end) | ||||
|         : name_(std::move(name)) | ||||
|         , sinks_(begin, end) | ||||
|     {} | ||||
| 
 | ||||
| 	logger(std::string name, sink_ptr single_sink) | ||||
|         : logger(std::move(name), {std::move(single_sink)}) | ||||
|     {} | ||||
|     logger(std::string name, sinks_init_list sinks) :  | ||||
| 		logger(std::move(name), sinks.begin(), sinks.end()) | ||||
| 	{} | ||||
| 
 | ||||
|     virtual ~logger() = default; | ||||
| 
 | ||||
|     logger(const logger &) = delete; | ||||
|     logger &operator=(const logger &) = delete; | ||||
| 
 | ||||
| 	template<typename... Args> | ||||
|     void log(source_loc loc, level::level_enum lvl, const char *fmt, const Args &... args) | ||||
| 	{ | ||||
|         if (!should_log(lvl)) | ||||
|     class logger | ||||
|     { | ||||
|     public: | ||||
|         template<typename It> | ||||
|         logger(std::string name, It begin, It end) | ||||
|             : name_(std::move(name)) | ||||
|             , sinks_(begin, end) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         try | ||||
|         logger(std::string name, sink_ptr single_sink) | ||||
|             : logger(std::move(name), {std::move(single_sink)}) | ||||
|         { | ||||
|             using details::fmt_helper::to_string_view; | ||||
|             fmt::memory_buffer buf; | ||||
|             fmt::format_to(buf, fmt, args...); | ||||
|             details::log_msg log_msg(loc, &name_, lvl, to_string_view(buf)); | ||||
|             sink_it_(log_msg); | ||||
|         } | ||||
|         SPDLOG_CATCH_AND_HANDLE | ||||
| 	} | ||||
| 
 | ||||
|     template<typename... Args> | ||||
| 	void log(level::level_enum lvl, const char *fmt, const Args &... args) | ||||
| 	{ | ||||
|         log(source_loc{}, lvl, fmt, args...); | ||||
| 	} | ||||
| 
 | ||||
|     | ||||
| 	void log(source_loc loc, level::level_enum lvl, const char *msg) | ||||
|     { | ||||
|         if (!should_log(lvl)) | ||||
|         logger(std::string name, sinks_init_list sinks) | ||||
|             : logger(std::move(name), sinks.begin(), sinks.end()) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         try | ||||
|         virtual ~logger() = default; | ||||
| 
 | ||||
|         logger(const logger &) = delete; | ||||
|         logger &operator=(const logger &) = delete; | ||||
| 
 | ||||
|         template<typename... Args> | ||||
|         void log(source_loc loc, level::level_enum lvl, const char *fmt, const Args &... args) | ||||
|         { | ||||
|             details::log_msg log_msg(loc, &name_, lvl, spdlog::string_view_t(msg)); | ||||
|             sink_it_(log_msg); | ||||
|             if (!should_log(lvl)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             try | ||||
|             {                 | ||||
|                 fmt::memory_buffer buf; | ||||
|                 fmt::format_to(buf, fmt, args...); | ||||
|                 details::log_msg log_msg(loc, &name_, lvl, string_view_t(buf.data(), buf.size())); | ||||
|                 sink_it_(log_msg); | ||||
|             } | ||||
|             catch (const std::exception &ex) | ||||
|             { | ||||
|                 err_handler_(ex.what()); | ||||
|             } | ||||
|             catch (...) | ||||
|             { | ||||
|                 err_handler_("Unknown exception in logger"); | ||||
|             } | ||||
|         } | ||||
|         SPDLOG_CATCH_AND_HANDLE | ||||
|     } | ||||
| 
 | ||||
|     void log(level::level_enum lvl, const char *msg) | ||||
|     { | ||||
|         log(source_loc{}, lvl, msg); | ||||
|     } | ||||
|         template<typename... Args> | ||||
|         void log(level::level_enum lvl, const char *fmt, const Args &... args) | ||||
|         { | ||||
|             log(source_loc{}, lvl, fmt, args...); | ||||
|         } | ||||
|         void log(source_loc loc, level::level_enum lvl, const char *msg); | ||||
|         void log(level::level_enum lvl, const char *msg); | ||||
| 
 | ||||
|      | ||||
|         template<typename... Args> | ||||
|         void trace(const char *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::trace, fmt, args...); | ||||
|         } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void trace(const char *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::trace, fmt, args...); | ||||
|     } | ||||
|         template<typename... Args> | ||||
|         void debug(const char *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::debug, fmt, args...); | ||||
|         } | ||||
| 
 | ||||
|         template<typename... Args> | ||||
|         void info(const char *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::info, fmt, args...); | ||||
|         } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void debug(const char *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::debug, fmt, args...); | ||||
|     } | ||||
|         template<typename... Args> | ||||
|         void warn(const char *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::warn, fmt, args...); | ||||
|         } | ||||
| 
 | ||||
|         template<typename... Args> | ||||
|         void error(const char *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::err, fmt, args...); | ||||
|         } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void info(const char *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::info, fmt, args...); | ||||
|     } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void warn(const char *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::warn, fmt, args...); | ||||
|     } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void error(const char *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::err, fmt, args...); | ||||
|     } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void critical(const char *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::critical, fmt, args...); | ||||
|     } | ||||
| 
 | ||||
|         template<typename... Args> | ||||
|         void critical(const char *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::critical, fmt, args...); | ||||
|         } | ||||
| 
 | ||||
| #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT | ||||
| #ifndef _WIN32 | ||||
| #error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows | ||||
| #else | ||||
|     inline void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target) | ||||
|     { | ||||
|         int wbuf_size = static_cast<int>(wbuf.size()); | ||||
|         if (wbuf_size == 0) | ||||
|         inline void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         auto result_size = ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, NULL, 0, NULL, NULL); | ||||
| 
 | ||||
|         if (result_size > 0) | ||||
|         { | ||||
|             target.resize(result_size); | ||||
|             ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, &target.data()[0], result_size, NULL, NULL); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             throw spdlog::spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	template<typename... Args> | ||||
|     void log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args) | ||||
|     { | ||||
|         if (!should_log(lvl)) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         try | ||||
|         { | ||||
|             // format to wmemory_buffer and convert to utf8
 | ||||
|             using details::fmt_helper::to_string_view; | ||||
|             fmt::wmemory_buffer wbuf; | ||||
|             fmt::format_to(wbuf, fmt, args...); | ||||
|             fmt::memory_buffer buf; | ||||
|             wbuf_to_utf8buf(wbuf, buf); | ||||
|             details::log_msg log_msg(source, &name_, lvl, to_string_view(buf)); | ||||
|             sink_it_(log_msg); | ||||
|         } | ||||
|         SPDLOG_CATCH_AND_HANDLE | ||||
|     } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args) | ||||
|     { | ||||
|         log(source_loc{}, lvl, fmt, args...); | ||||
|     } | ||||
|    | ||||
|     template<typename... Args> | ||||
|     void trace(const wchar_t *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::trace, fmt, args...); | ||||
|     } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void debug(const wchar_t *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::debug, fmt, args...); | ||||
|     } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void info(const wchar_t *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::info, fmt, args...); | ||||
|     } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void warn(const wchar_t *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::warn, fmt, args...); | ||||
|     } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void error(const wchar_t *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::err, fmt, args...); | ||||
|     } | ||||
| 
 | ||||
|     template<typename... Args> | ||||
|     void critical(const wchar_t *fmt, const Args &... args) | ||||
|     { | ||||
|         log(level::critical, fmt, args...); | ||||
|     } | ||||
| #endif // _WIN32
 | ||||
| #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
 | ||||
| 
 | ||||
|     template<typename T> | ||||
|     void log(level::level_enum lvl, const T &msg) | ||||
|     { | ||||
|         log(source_loc{}, lvl, msg); | ||||
|     } | ||||
| 
 | ||||
|     // T can be statically converted to string_view
 | ||||
|     template<class T, typename std::enable_if<std::is_convertible<T, spdlog::string_view_t>::value, T>::type * = nullptr> | ||||
|     void log(source_loc loc, level::level_enum lvl, const T &msg) | ||||
|     { | ||||
|         if (!should_log(lvl)) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             details::log_msg log_msg(loc, &name_, lvl, msg); | ||||
|             sink_it_(log_msg); | ||||
|         } | ||||
|         SPDLOG_CATCH_AND_HANDLE | ||||
|     } | ||||
| 
 | ||||
|     // T cannot be statically converted to string_view
 | ||||
|     template<class T, typename std::enable_if<!std::is_convertible<T, spdlog::string_view_t>::value, T>::type * = nullptr> | ||||
|     void log(source_loc loc, level::level_enum lvl, const T &msg) | ||||
|     { | ||||
|         if (!should_log(lvl)) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             using details::fmt_helper::to_string_view; | ||||
|             fmt::memory_buffer buf; | ||||
|             fmt::format_to(buf, "{}", msg); | ||||
|             details::log_msg log_msg(loc, &name_, lvl, to_string_view(buf)); | ||||
|             sink_it_(log_msg); | ||||
|         } | ||||
|         SPDLOG_CATCH_AND_HANDLE | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     void trace(const T &msg) | ||||
|     { | ||||
|         log(level::trace, msg); | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     void debug(const T &msg) | ||||
|     { | ||||
|         log(level::debug, msg); | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     void info(const T &msg) | ||||
|     { | ||||
|         log(level::info, msg); | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     void warn(const T &msg) | ||||
|     { | ||||
|         log(level::warn, msg); | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     void error(const T &msg) | ||||
|     { | ||||
|         log(level::err, msg); | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     void critical(const T &msg) | ||||
|     { | ||||
|         log(level::critical, msg); | ||||
|     } | ||||
| 
 | ||||
|     bool should_log(level::level_enum msg_level) const | ||||
|     { | ||||
|         return msg_level >= level_.load(std::memory_order_relaxed); | ||||
|     } | ||||
| 
 | ||||
|     void set_level(level::level_enum log_level) | ||||
|     { | ||||
|         level_.store(log_level); | ||||
|     } | ||||
| 
 | ||||
|     static level::level_enum default_level() | ||||
|     { | ||||
|         return static_cast<spdlog::level::level_enum>(SPDLOG_ACTIVE_LEVEL); | ||||
|     } | ||||
| 
 | ||||
|     level::level_enum level() const | ||||
|     { | ||||
|         return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed)); | ||||
|     } | ||||
| 
 | ||||
|     const std::string &name() const | ||||
|     { | ||||
|         return name_; | ||||
|     } | ||||
| 
 | ||||
|     // set formatting for the sinks in this logger.
 | ||||
|     // each sink will get a seperate instance of the formatter object.
 | ||||
|     void set_formatter(std::unique_ptr<formatter> f) | ||||
|     { | ||||
|         for (auto &sink : sinks_) | ||||
|         { | ||||
|             sink->set_formatter(f->clone()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local) | ||||
|     { | ||||
|         auto new_formatter = details::make_unique<spdlog::pattern_formatter>(std::move(pattern), time_type); | ||||
|         set_formatter(std::move(new_formatter)); | ||||
|     } | ||||
| 
 | ||||
|     // flush functions
 | ||||
|     void flush() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             flush_(); | ||||
|         } | ||||
|         SPDLOG_CATCH_AND_HANDLE | ||||
|     } | ||||
| 
 | ||||
|     void flush_on(level::level_enum log_level) | ||||
|     { | ||||
|         flush_level_.store(log_level); | ||||
|     } | ||||
| 
 | ||||
|     level::level_enum flush_level() const | ||||
|     { | ||||
|         return static_cast<spdlog::level::level_enum>(flush_level_.load(std::memory_order_relaxed)); | ||||
|     } | ||||
| 
 | ||||
|     // sinks
 | ||||
|     const std::vector<sink_ptr> &sinks() const | ||||
|     { | ||||
|         return sinks_; | ||||
|     } | ||||
| 
 | ||||
|     std::vector<sink_ptr> &sinks() | ||||
|     { | ||||
|         return sinks_; | ||||
|     } | ||||
| 
 | ||||
|     // error handler
 | ||||
|     void set_error_handler(log_err_handler err_handler) | ||||
|     { | ||||
|         err_handler_ = std::move(err_handler); | ||||
|     } | ||||
| 
 | ||||
|     log_err_handler error_handler() const | ||||
|     { | ||||
|         return err_handler_; | ||||
|     } | ||||
| 
 | ||||
|     // create new logger with same sinks and configuration.
 | ||||
|     virtual std::shared_ptr<logger> clone(std::string logger_name) | ||||
|     { | ||||
|         auto cloned = std::make_shared<spdlog::logger>(std::move(logger_name), sinks_.begin(), sinks_.end()); | ||||
|         cloned->set_level(this->level()); | ||||
|         cloned->flush_on(this->flush_level()); | ||||
|         cloned->set_error_handler(this->error_handler()); | ||||
|         return cloned; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| protected: | ||||
|     virtual void sink_it_(details::log_msg &msg) | ||||
|     { | ||||
| #if defined(SPDLOG_ENABLE_MESSAGE_COUNTER) | ||||
|         incr_msg_counter_(msg); | ||||
| #endif | ||||
|         for (auto &sink : sinks_) | ||||
|         { | ||||
|             if (sink->should_log(msg.level)) | ||||
|             int wbuf_size = static_cast<int>(wbuf.size()); | ||||
|             if (wbuf_size == 0) | ||||
|             { | ||||
|                 sink->log(msg); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             auto result_size = ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, NULL, 0, NULL, NULL); | ||||
| 
 | ||||
|             if (result_size > 0) | ||||
|             { | ||||
|                 target.resize(result_size); | ||||
|                 ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, &target.data()[0], result_size, NULL, NULL); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 throw spdlog::spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (should_flush_(msg)) | ||||
|         template<typename... Args> | ||||
|         void log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args) | ||||
|         { | ||||
|             flush_(); | ||||
|         } | ||||
|     } | ||||
|             if (!should_log(lvl)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|     virtual void flush_() | ||||
|     { | ||||
|         for (auto &sink : sinks_) | ||||
|             try | ||||
|             { | ||||
|                 // format to wmemory_buffer and convert to utf8
 | ||||
|                 using details::fmt_helper::to_string_view; | ||||
|                 fmt::wmemory_buffer wbuf; | ||||
|                 fmt::format_to(wbuf, fmt, args...); | ||||
|                 fmt::memory_buffer buf; | ||||
|                 wbuf_to_utf8buf(wbuf, buf); | ||||
|                 details::log_msg log_msg(source, &name_, lvl, to_string_view(buf)); | ||||
|                 sink_it_(log_msg); | ||||
|             } | ||||
|             SPDLOG_CATCH_AND_HANDLE | ||||
|         } | ||||
| 
 | ||||
|         template<typename... Args> | ||||
|         void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args) | ||||
|         { | ||||
|             sink->flush(); | ||||
|             log(source_loc{}, lvl, fmt, args...); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     bool should_flush_(const details::log_msg &msg) | ||||
|     { | ||||
|         auto flush_level = flush_level_.load(std::memory_order_relaxed); | ||||
|         return (msg.level >= flush_level) && (msg.level != level::off); | ||||
|     } | ||||
| 
 | ||||
|     // default error handler.
 | ||||
|     // print the error to stderr with the max rate of 1 message/minute.
 | ||||
|     void default_err_handler_(const std::string &msg) | ||||
|     { | ||||
|         auto now = time(nullptr); | ||||
|         if (now - last_err_time_ < 60) | ||||
|         template<typename... Args> | ||||
|         void trace(const wchar_t *fmt, const Args &... args) | ||||
|         { | ||||
|             return; | ||||
|             log(level::trace, fmt, args...); | ||||
|         } | ||||
|         last_err_time_ = now; | ||||
|         auto tm_time = details::os::localtime(now); | ||||
|         char date_buf[100]; | ||||
|         std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); | ||||
|         fmt::print(stderr, "[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, name(), msg); | ||||
|     } | ||||
| 
 | ||||
|     // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
 | ||||
|     void incr_msg_counter_(details::log_msg &msg) | ||||
|     { | ||||
|         msg.msg_id = msg_counter_.fetch_add(1, std::memory_order_relaxed); | ||||
|     } | ||||
|         template<typename... Args> | ||||
|         void debug(const wchar_t *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::debug, fmt, args...); | ||||
|         } | ||||
| 
 | ||||
|     const std::string name_; | ||||
|     std::vector<sink_ptr> sinks_; | ||||
|     spdlog::level_t level_{spdlog::logger::default_level()}; | ||||
|     spdlog::level_t flush_level_{level::off}; | ||||
|     log_err_handler err_handler_{[this](const std::string &msg) { this->default_err_handler_(msg); }}; | ||||
|     std::atomic<time_t> last_err_time_{0}; | ||||
|     std::atomic<size_t> msg_counter_{1}; | ||||
| }; | ||||
|         template<typename... Args> | ||||
|         void info(const wchar_t *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::info, fmt, args...); | ||||
|         } | ||||
| 
 | ||||
|         template<typename... Args> | ||||
|         void warn(const wchar_t *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::warn, fmt, args...); | ||||
|         } | ||||
| 
 | ||||
|         template<typename... Args> | ||||
|         void error(const wchar_t *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::err, fmt, args...); | ||||
|         } | ||||
| 
 | ||||
|         template<typename... Args> | ||||
|         void critical(const wchar_t *fmt, const Args &... args) | ||||
|         { | ||||
|             log(level::critical, fmt, args...); | ||||
|         } | ||||
| #endif // _WIN32
 | ||||
| #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
 | ||||
| 
 | ||||
|         template<typename T> | ||||
|         void log(level::level_enum lvl, const T &msg) | ||||
|         { | ||||
|             log(source_loc{}, lvl, msg); | ||||
|         } | ||||
| 
 | ||||
|         // T can be statically converted to string_view
 | ||||
|         template<class T, typename std::enable_if<std::is_convertible<T, spdlog::string_view_t>::value, T>::type * = nullptr> | ||||
|         void log(source_loc loc, level::level_enum lvl, const T &msg) | ||||
|         { | ||||
|             if (!should_log(lvl)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             try | ||||
|             { | ||||
|                 details::log_msg log_msg(loc, &name_, lvl, msg); | ||||
|                 sink_it_(log_msg); | ||||
|             } | ||||
|             catch (const std::exception &ex) | ||||
|             { | ||||
|                 err_handler_(ex.what()); | ||||
|             } | ||||
|             catch (...) | ||||
|             { | ||||
|                 err_handler_("Unknown exception in logger"); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // T cannot be statically converted to string_view
 | ||||
|         template<class T, typename std::enable_if<!std::is_convertible<T, spdlog::string_view_t>::value, T>::type * = nullptr> | ||||
|         void log(source_loc loc, level::level_enum lvl, const T &msg) | ||||
|         { | ||||
|             if (!should_log(lvl)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             try | ||||
|             { | ||||
|                 using details::fmt_helper::to_string_view; | ||||
|                 fmt::memory_buffer buf; | ||||
|                 fmt::format_to(buf, "{}", msg); | ||||
|                 details::log_msg log_msg(loc, &name_, lvl, to_string_view(buf)); | ||||
|                 sink_it_(log_msg); | ||||
|             } | ||||
|             catch (const std::exception &ex) | ||||
|             { | ||||
|                 err_handler_(ex.what()); | ||||
|             } | ||||
|             catch (...) | ||||
|             { | ||||
|                 err_handler_("Unknown exception in logger"); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         template<typename T> | ||||
|         void trace(const T &msg) | ||||
|         { | ||||
|             log(level::trace, msg); | ||||
|         } | ||||
| 
 | ||||
|         template<typename T> | ||||
|         void debug(const T &msg) | ||||
|         { | ||||
|             log(level::debug, msg); | ||||
|         } | ||||
| 
 | ||||
|         template<typename T> | ||||
|         void info(const T &msg) | ||||
|         { | ||||
|             log(level::info, msg); | ||||
|         } | ||||
| 
 | ||||
|         template<typename T> | ||||
|         void warn(const T &msg) | ||||
|         { | ||||
|             log(level::warn, msg); | ||||
|         } | ||||
| 
 | ||||
|         template<typename T> | ||||
|         void error(const T &msg) | ||||
|         { | ||||
|             log(level::err, msg); | ||||
|         } | ||||
| 
 | ||||
|         template<typename T> | ||||
|         void critical(const T &msg) | ||||
|         { | ||||
|             log(level::critical, msg); | ||||
|         } | ||||
| 
 | ||||
|         bool should_log(level::level_enum msg_level) const; | ||||
| 
 | ||||
|         void set_level(level::level_enum log_level); | ||||
| 
 | ||||
|         static level::level_enum default_level(); | ||||
| 
 | ||||
|         level::level_enum level() const; | ||||
| 
 | ||||
|         const std::string &name() const; | ||||
| 
 | ||||
|         // set formatting for the sinks in this logger.
 | ||||
|         // each sink will get a seperate instance of the formatter object.
 | ||||
|         void set_formatter(std::unique_ptr<formatter> f); | ||||
| 
 | ||||
|         void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local); | ||||
| 
 | ||||
|         // flush functions
 | ||||
|         void flush(); | ||||
|         void flush_on(level::level_enum log_level); | ||||
|         level::level_enum flush_level() const; | ||||
| 
 | ||||
|         // sinks
 | ||||
|         const std::vector<sink_ptr> &sinks() const; | ||||
| 
 | ||||
|         std::vector<sink_ptr> &sinks(); | ||||
| 
 | ||||
|         // error handler
 | ||||
|         void set_error_handler(log_err_handler err_handler); | ||||
| 
 | ||||
|         log_err_handler error_handler() const; | ||||
| 
 | ||||
|         // create new logger with same sinks and configuration.
 | ||||
|         virtual std::shared_ptr<logger> clone(std::string logger_name); | ||||
| 
 | ||||
|     protected: | ||||
|         virtual void sink_it_(details::log_msg &msg); | ||||
| 
 | ||||
|         virtual void flush_(); | ||||
|         bool should_flush_(const details::log_msg &msg); | ||||
| 
 | ||||
|         // default error handler.
 | ||||
|         // print the error to stderr with the max rate of 1 message/minute.
 | ||||
|         void default_err_handler_(const std::string &msg); | ||||
| 
 | ||||
|         // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
 | ||||
|         void incr_msg_counter_(details::log_msg &msg); | ||||
| 
 | ||||
|         const std::string name_; | ||||
|         std::vector<sink_ptr> sinks_; | ||||
|         spdlog::level_t level_{spdlog::logger::default_level()}; | ||||
|         spdlog::level_t flush_level_{level::off}; | ||||
|         log_err_handler err_handler_{[this](const std::string &msg) { this->default_err_handler_(msg); }}; | ||||
|         std::atomic<time_t> last_err_time_{0}; | ||||
|         std::atomic<size_t> msg_counter_{1}; | ||||
|     }; | ||||
| } // namespace spdlog
 | ||||
| 
 | ||||
| #ifdef SPDLOG_HEADER_ONLY | ||||
| #include "../src/logger.cpp" | ||||
| #endif // SPDLOG_HEADER_ONLY
 | ||||
|  | ||||
| @ -6,49 +6,41 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "spdlog/details/log_msg.h" | ||||
| #include "spdlog/details/pattern_formatter.h" | ||||
| //#include "spdlog/details/pattern_formatter.h"
 | ||||
| #include "spdlog/formatter.h" | ||||
| 
 | ||||
| namespace spdlog { | ||||
| 
 | ||||
| namespace sinks { | ||||
| class sink | ||||
| { | ||||
| public: | ||||
|     sink() = default; | ||||
| 
 | ||||
|     explicit sink(std::unique_ptr<spdlog::formatter> formatter) | ||||
|         : formatter_{std::move(formatter)} | ||||
|     { | ||||
|     } | ||||
|     sink(); | ||||
| 
 | ||||
|     explicit sink(std::unique_ptr<spdlog::formatter> formatter);     | ||||
|     virtual ~sink() = default; | ||||
|     virtual void log(const details::log_msg &msg) = 0; | ||||
|     virtual void flush() = 0; | ||||
|     virtual void set_pattern(const std::string &pattern) = 0; | ||||
|     virtual void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) = 0; | ||||
| 
 | ||||
|     bool should_log(level::level_enum msg_level) const | ||||
|     { | ||||
|         return msg_level >= level_.load(std::memory_order_relaxed); | ||||
|     } | ||||
| 
 | ||||
|     void set_level(level::level_enum log_level) | ||||
|     { | ||||
|         level_.store(log_level); | ||||
|     } | ||||
| 
 | ||||
|     level::level_enum level() const | ||||
|     { | ||||
|         return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed)); | ||||
|     } | ||||
|     bool should_log(level::level_enum msg_level) const; | ||||
|      | ||||
|     void set_level(level::level_enum log_level); | ||||
|      | ||||
|     level::level_enum level() const; | ||||
| 
 | ||||
| protected: | ||||
|     // sink log level - default is all
 | ||||
|     level_t level_{level::trace}; | ||||
| 
 | ||||
|     // sink formatter - default is full format
 | ||||
|     std::unique_ptr<spdlog::formatter> formatter_{details::make_unique<spdlog::pattern_formatter>()}; | ||||
|     // sink formatter
 | ||||
|     std::unique_ptr<spdlog::formatter> formatter_; | ||||
| }; | ||||
| 
 | ||||
| } // namespace sinks
 | ||||
| } // namespace spdlog
 | ||||
| 
 | ||||
| #ifdef SPDLOG_HEADER_ONLY | ||||
| #include "../src/sink.cpp" | ||||
| #endif // SPDLOG_HEADER_ONLY
 | ||||
|  | ||||
							
								
								
									
										29
									
								
								src/log_msg.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/log_msg.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| #include "spdlog/details/os.h" | ||||
| #include "spdlog/sinks/sink.h" | ||||
| 
 | ||||
| #ifndef SPDLOG_HEADER_ONLY | ||||
| #include "spdlog/details/log_msg.h" | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| SPDLOG_INLINE spdlog::details::log_msg::log_msg( | ||||
|     spdlog::source_loc loc, const std::string *loggers_name, spdlog::level::level_enum lvl, spdlog::string_view_t view) | ||||
|     : logger_name(loggers_name) | ||||
|     , level(lvl) | ||||
| #ifndef SPDLOG_NO_DATETIME | ||||
|     , time(os::now()) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef SPDLOG_NO_THREAD_ID | ||||
|     , thread_id(os::thread_id()) | ||||
| #endif | ||||
|     , source(loc) | ||||
|     , payload(view) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE spdlog::details::log_msg::log_msg(const std::string *loggers_name, spdlog::level::level_enum lvl, spdlog::string_view_t view) | ||||
|     : log_msg(source_loc{}, loggers_name, lvl, view) | ||||
| { | ||||
| } | ||||
							
								
								
									
										187
									
								
								src/logger.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								src/logger.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,187 @@ | ||||
| #ifndef SPDLOG_HEADER_ONLY | ||||
| #include "spdlog/logger.h" | ||||
| #endif | ||||
| 
 | ||||
| #include "spdlog/sinks/sink.h" | ||||
| #include "spdlog/details/pattern_formatter.h" | ||||
| 
 | ||||
| // public methods
 | ||||
| SPDLOG_INLINE void spdlog::logger::log(spdlog::source_loc loc, spdlog::level::level_enum lvl, const char *msg) | ||||
| { | ||||
|     if (!should_log(lvl)) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     try | ||||
|     { | ||||
|         details::log_msg log_msg(loc, &name_, lvl, spdlog::string_view_t(msg)); | ||||
|         sink_it_(log_msg); | ||||
|     } | ||||
|     catch (const std::exception &ex) | ||||
|     { | ||||
|         err_handler_(ex.what()); | ||||
|     } | ||||
|     catch (...) | ||||
|     { | ||||
|         err_handler_("Unknown exception in logger"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE void spdlog::logger::log(level::level_enum lvl, const char *msg) | ||||
| { | ||||
|     log(source_loc{}, lvl, msg); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const | ||||
| { | ||||
|     return msg_level >= level_.load(std::memory_order_relaxed); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE void spdlog::logger::set_level(spdlog::level::level_enum log_level) | ||||
| { | ||||
|     level_.store(log_level); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE spdlog::level::level_enum spdlog::logger::default_level() | ||||
| { | ||||
|     return static_cast<spdlog::level::level_enum>(SPDLOG_ACTIVE_LEVEL); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE spdlog::level::level_enum spdlog::logger::level() const | ||||
| { | ||||
|     return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed)); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE const std::string &spdlog::logger::name() const | ||||
| { | ||||
|     return name_; | ||||
| } | ||||
| 
 | ||||
| // set formatting for the sinks in this logger.
 | ||||
| // each sink will get a seperate instance of the formatter object.
 | ||||
| SPDLOG_INLINE void spdlog::logger::set_formatter(std::unique_ptr<spdlog::formatter> f) | ||||
| { | ||||
|     for (auto &sink : sinks_) | ||||
|     { | ||||
|         sink->set_formatter(f->clone()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE void spdlog::logger::set_pattern(std::string pattern, spdlog::pattern_time_type time_type) | ||||
| { | ||||
|     auto new_formatter = details::make_unique<spdlog::pattern_formatter>(std::move(pattern), time_type); | ||||
|     set_formatter(std::move(new_formatter)); | ||||
| } | ||||
| 
 | ||||
| // flush functions
 | ||||
| SPDLOG_INLINE void spdlog::logger::flush() | ||||
| { | ||||
|     try | ||||
|     { | ||||
|         flush_(); | ||||
|     } | ||||
|     catch (const std::exception &ex) | ||||
|     { | ||||
|         err_handler_(ex.what()); | ||||
|     } | ||||
|     catch (...) | ||||
|     { | ||||
|         err_handler_("Unknown exception in logger"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE void spdlog::logger::flush_on(level::level_enum log_level) | ||||
| { | ||||
|     flush_level_.store(log_level); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE spdlog::level::level_enum spdlog::logger::flush_level() const | ||||
| { | ||||
|     return static_cast<spdlog::level::level_enum>(flush_level_.load(std::memory_order_relaxed)); | ||||
| } | ||||
| 
 | ||||
| // sinks
 | ||||
| SPDLOG_INLINE const std::vector<spdlog::sink_ptr> &spdlog::logger::sinks() const | ||||
| { | ||||
|     return sinks_; | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE std::vector<spdlog::sink_ptr> &spdlog::logger::sinks() | ||||
| { | ||||
|     return sinks_; | ||||
| } | ||||
| 
 | ||||
| // error handler
 | ||||
| SPDLOG_INLINE void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler) | ||||
| { | ||||
|     err_handler_ = std::move(err_handler); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE spdlog::log_err_handler spdlog::logger::error_handler() const | ||||
| { | ||||
|     return err_handler_; | ||||
| } | ||||
| 
 | ||||
| // create new logger with same sinks and configuration.
 | ||||
| SPDLOG_INLINE std::shared_ptr<spdlog::logger> spdlog::logger::clone(std::string logger_name) | ||||
| { | ||||
|     auto cloned = std::make_shared<spdlog::logger>(std::move(logger_name), sinks_.begin(), sinks_.end()); | ||||
|     cloned->set_level(this->level()); | ||||
|     cloned->flush_on(this->flush_level()); | ||||
|     cloned->set_error_handler(this->error_handler()); | ||||
|     return cloned; | ||||
| } | ||||
| 
 | ||||
| // protected methods
 | ||||
| SPDLOG_INLINE void spdlog::logger::sink_it_(spdlog::details::log_msg &msg) | ||||
| { | ||||
| #if defined(SPDLOG_ENABLE_MESSAGE_COUNTER) | ||||
|     incr_msg_counter_(msg); | ||||
| #endif | ||||
|     for (auto &sink : sinks_) | ||||
|     { | ||||
|         if (sink->should_log(msg.level)) | ||||
|         { | ||||
|             sink->log(msg); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (should_flush_(msg)) | ||||
|     { | ||||
|         flush_(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE void spdlog::logger::flush_() | ||||
| { | ||||
|     for (auto &sink : sinks_) | ||||
|     { | ||||
|         sink->flush(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE bool spdlog::logger::should_flush_(const spdlog::details::log_msg &msg) | ||||
| { | ||||
|     auto flush_level = flush_level_.load(std::memory_order_relaxed); | ||||
|     return (msg.level >= flush_level) && (msg.level != level::off); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE void spdlog::logger::default_err_handler_(const std::string &msg) | ||||
| { | ||||
|     auto now = time(nullptr); | ||||
|     if (now - last_err_time_ < 60) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
|     last_err_time_ = now; | ||||
|     auto tm_time = details::os::localtime(now); | ||||
|     char date_buf[100]; | ||||
|     std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); | ||||
|     fmt::print(stderr, "[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, name(), msg); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE void spdlog::logger::incr_msg_counter_(spdlog::details::log_msg &msg) | ||||
| { | ||||
|     msg.msg_id = msg_counter_.fetch_add(1, std::memory_order_relaxed); | ||||
| } | ||||
							
								
								
									
										406
									
								
								src/os.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										406
									
								
								src/os.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,406 @@ | ||||
| //
 | ||||
| // Copyright(c) 2015 Gabi Melman.
 | ||||
| // Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | ||||
| //
 | ||||
| #pragma once | ||||
| 
 | ||||
| #ifndef SPDLOG_HEADER_ONLY | ||||
| #include "spdlog/details/os.h" | ||||
| #include "spdlog/common.h" | ||||
| #endif | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <chrono> | ||||
| #include <cstdio> | ||||
| #include <cstdlib> | ||||
| #include <cstring> | ||||
| #include <ctime> | ||||
| #include <functional> | ||||
| #include <string> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/types.h> | ||||
| #include <thread> | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| 
 | ||||
| #ifndef NOMINMAX | ||||
| #define NOMINMAX // prevent windows redefining min/max
 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef WIN32_LEAN_AND_MEAN | ||||
| #define WIN32_LEAN_AND_MEAN | ||||
| #endif | ||||
| #include <io.h>      // _get_osfhandle and _isatty support
 | ||||
| #include <process.h> //  _get_pid support
 | ||||
| #include <windows.h> | ||||
| 
 | ||||
| #ifdef __MINGW32__ | ||||
| #include <share.h> | ||||
| #endif | ||||
| 
 | ||||
| #else // unix
 | ||||
| 
 | ||||
| #include <fcntl.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #ifdef __linux__ | ||||
| #include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
 | ||||
| 
 | ||||
| #elif __FreeBSD__ | ||||
| #include <sys/thr.h> //Use thr_self() syscall under FreeBSD to get thread id
 | ||||
| #endif | ||||
| 
 | ||||
| #endif // unix
 | ||||
| 
 | ||||
| #ifndef __has_feature      // Clang - feature checking macros.
 | ||||
| #define __has_feature(x) 0 // Compatibility with non-clang compilers.
 | ||||
| #endif | ||||
| 
 | ||||
| namespace spdlog { | ||||
| namespace details { | ||||
| namespace os { | ||||
| 
 | ||||
| SPDLOG_INLINE spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT | ||||
| { | ||||
| 
 | ||||
| #if defined __linux__ && defined SPDLOG_CLOCK_COARSE | ||||
|     timespec ts; | ||||
|     ::clock_gettime(CLOCK_REALTIME_COARSE, &ts); | ||||
|     return std::chrono::time_point<log_clock, typename log_clock::duration>( | ||||
|         std::chrono::duration_cast<typename log_clock::duration>(std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec))); | ||||
| 
 | ||||
| #else | ||||
|     return log_clock::now(); | ||||
| #endif | ||||
| } | ||||
| SPDLOG_INLINE std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     std::tm tm; | ||||
|     localtime_s(&tm, &time_tt); | ||||
| #else | ||||
|     std::tm tm; | ||||
|     localtime_r(&time_tt, &tm); | ||||
| #endif | ||||
|     return tm; | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE std::tm localtime() SPDLOG_NOEXCEPT | ||||
| { | ||||
|     std::time_t now_t = time(nullptr); | ||||
|     return localtime(now_t); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     std::tm tm; | ||||
|     gmtime_s(&tm, &time_tt); | ||||
| #else | ||||
|     std::tm tm; | ||||
|     gmtime_r(&time_tt, &tm); | ||||
| #endif | ||||
|     return tm; | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE std::tm gmtime() SPDLOG_NOEXCEPT | ||||
| { | ||||
|     std::time_t now_t = time(nullptr); | ||||
|     return gmtime(now_t); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE void prevent_child_fd(FILE *f) | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #if !defined(__cplusplus_winrt) | ||||
|     auto file_handle = (HANDLE)_get_osfhandle(_fileno(f)); | ||||
|     if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)) | ||||
|         throw spdlog_ex("SetHandleInformation failed", errno); | ||||
| #endif | ||||
| #else | ||||
|     auto fd = fileno(f); | ||||
|     if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) | ||||
|     { | ||||
|         throw spdlog_ex("fcntl with FD_CLOEXEC failed", errno); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // fopen_s on non windows for writing
 | ||||
| SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) | ||||
| { | ||||
| #ifdef _WIN32 | ||||
| #ifdef SPDLOG_WCHAR_FILENAMES | ||||
|     *fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); | ||||
| #else | ||||
|     *fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); | ||||
| #endif | ||||
| #else // unix
 | ||||
|     *fp = fopen((filename.c_str()), mode.c_str()); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef SPDLOG_PREVENT_CHILD_FD | ||||
|     if (*fp != nullptr) | ||||
|     { | ||||
|         prevent_child_fd(*fp); | ||||
|     } | ||||
| #endif | ||||
|     return *fp == nullptr; | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE int remove(const filename_t &filename) SPDLOG_NOEXCEPT | ||||
| { | ||||
| #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) | ||||
|     return _wremove(filename.c_str()); | ||||
| #else | ||||
|     return std::remove(filename.c_str()); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT | ||||
| { | ||||
| #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) | ||||
|     return _wrename(filename1.c_str(), filename2.c_str()); | ||||
| #else | ||||
|     return std::rename(filename1.c_str(), filename2.c_str()); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // Return if file exists
 | ||||
| SPDLOG_INLINE bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT | ||||
| { | ||||
| #ifdef _WIN32 | ||||
| #ifdef SPDLOG_WCHAR_FILENAMES | ||||
|     auto attribs = GetFileAttributesW(filename.c_str()); | ||||
| #else | ||||
|     auto attribs = GetFileAttributesA(filename.c_str()); | ||||
| #endif | ||||
|     return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY)); | ||||
| #else // common linux/unix all have the stat system call
 | ||||
|     struct stat buffer; | ||||
|     return (stat(filename.c_str(), &buffer) == 0); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // Return file size according to open FILE* object
 | ||||
| SPDLOG_INLINE size_t filesize(FILE *f) | ||||
| { | ||||
|     if (f == nullptr) | ||||
|     { | ||||
|         throw spdlog_ex("Failed getting file size. fd is null"); | ||||
|     } | ||||
| #if defined(_WIN32) && !defined(__CYGWIN__) | ||||
|     int fd = _fileno(f); | ||||
| #if _WIN64 // 64 bits
 | ||||
|     __int64 ret = _filelengthi64(fd); | ||||
|     if (ret >= 0) | ||||
|     { | ||||
|         return static_cast<size_t>(ret); | ||||
|     } | ||||
| 
 | ||||
| #else // windows 32 bits
 | ||||
|     long ret = _filelength(fd); | ||||
|     if (ret >= 0) | ||||
|     { | ||||
|         return static_cast<size_t>(ret); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
| #else // unix
 | ||||
|     int fd = fileno(f); | ||||
| // 64 bits(but not in osx or cygwin, where fstat64 is deprecated)
 | ||||
| #if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) && !defined(__CYGWIN__) | ||||
|     struct stat64 st; | ||||
|     if (fstat64(fd, &st) == 0) | ||||
|     { | ||||
|         return static_cast<size_t>(st.st_size); | ||||
|     } | ||||
| #else // unix 32 bits or cygwin
 | ||||
|     struct stat st; | ||||
| 
 | ||||
|     if (fstat(fd, &st) == 0) | ||||
|     { | ||||
|         return static_cast<size_t>(st.st_size); | ||||
|     } | ||||
| #endif | ||||
| #endif | ||||
|     throw spdlog_ex("Failed getting file size from fd", errno); | ||||
| } | ||||
| 
 | ||||
| // Return utc offset in minutes or throw spdlog_ex on failure
 | ||||
| SPDLOG_INLINE int utc_minutes_offset(const std::tm &tm) | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #if _WIN32_WINNT < _WIN32_WINNT_WS08 | ||||
|     TIME_ZONE_INFORMATION tzinfo; | ||||
|     auto rv = GetTimeZoneInformation(&tzinfo); | ||||
| #else | ||||
|     DYNAMIC_TIME_ZONE_INFORMATION tzinfo; | ||||
|     auto rv = GetDynamicTimeZoneInformation(&tzinfo); | ||||
| #endif | ||||
|     if (rv == TIME_ZONE_ID_INVALID) | ||||
|         throw spdlog::spdlog_ex("Failed getting timezone info. ", errno); | ||||
| 
 | ||||
|     int offset = -tzinfo.Bias; | ||||
|     if (tm.tm_isdst) | ||||
|     { | ||||
|         offset -= tzinfo.DaylightBias; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         offset -= tzinfo.StandardBias; | ||||
|     } | ||||
|     return offset; | ||||
| #else | ||||
| 
 | ||||
| #if defined(sun) || defined(__sun) || defined(_AIX) | ||||
|     // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
 | ||||
|     struct helper | ||||
|     { | ||||
|         static long int calculate_gmt_offset(const std::tm &localtm = details::os::localtime(), const std::tm &gmtm = details::os::gmtime()) | ||||
|         { | ||||
|             int local_year = localtm.tm_year + (1900 - 1); | ||||
|             int gmt_year = gmtm.tm_year + (1900 - 1); | ||||
| 
 | ||||
|             long int days = ( | ||||
|                 // difference in day of year
 | ||||
|                 localtm.tm_yday - | ||||
|                 gmtm.tm_yday | ||||
| 
 | ||||
|                 // + intervening leap days
 | ||||
|                 + ((local_year >> 2) - (gmt_year >> 2)) - (local_year / 100 - gmt_year / 100) + | ||||
|                 ((local_year / 100 >> 2) - (gmt_year / 100 >> 2)) | ||||
| 
 | ||||
|                 // + difference in years * 365 */
 | ||||
|                 + (long int)(local_year - gmt_year) * 365); | ||||
| 
 | ||||
|             long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour); | ||||
|             long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min); | ||||
|             long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec); | ||||
| 
 | ||||
|             return secs; | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     auto offset_seconds = helper::calculate_gmt_offset(tm); | ||||
| #else | ||||
|     auto offset_seconds = tm.tm_gmtoff; | ||||
| #endif | ||||
| 
 | ||||
|     return static_cast<int>(offset_seconds / 60); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // Return current thread id as size_t
 | ||||
| // It exists because the std::this_thread::get_id() is much slower(especially
 | ||||
| // under VS 2013)
 | ||||
| SPDLOG_INLINE size_t _thread_id() SPDLOG_NOEXCEPT | ||||
| { | ||||
| #ifdef _WIN32 | ||||
|     return static_cast<size_t>(::GetCurrentThreadId()); | ||||
| #elif __linux__ | ||||
| #if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) | ||||
| #define SYS_gettid __NR_gettid | ||||
| #endif | ||||
|     return static_cast<size_t>(syscall(SYS_gettid)); | ||||
| #elif __FreeBSD__ | ||||
|     long tid; | ||||
|     thr_self(&tid); | ||||
|     return static_cast<size_t>(tid); | ||||
| #elif __APPLE__ | ||||
|     uint64_t tid; | ||||
|     pthread_threadid_np(nullptr, &tid); | ||||
|     return static_cast<size_t>(tid); | ||||
| #else // Default to standard C++11 (other Unix)
 | ||||
|     return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id())); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // Return current thread id as size_t (from thread local storage)
 | ||||
| SPDLOG_INLINE size_t thread_id() SPDLOG_NOEXCEPT | ||||
| { | ||||
| #if defined(SPDLOG_NO_TLS) | ||||
|     return _thread_id(); | ||||
| #else // cache thread id in tls
 | ||||
|     static thread_local const size_t tid = _thread_id(); | ||||
|     return tid; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // This is avoid msvc issue in sleep_for that happens if the clock changes.
 | ||||
| // See https://github.com/gabime/spdlog/issues/609
 | ||||
| SPDLOG_INLINE void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT | ||||
| { | ||||
| #if defined(_WIN32) | ||||
|     ::Sleep(milliseconds); | ||||
| #else | ||||
|     std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
 | ||||
| #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) | ||||
| #define SPDLOG_FILENAME_T(s) L##s | ||||
| SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) | ||||
| { | ||||
|     std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> c; | ||||
|     return c.to_bytes(filename); | ||||
| } | ||||
| #else | ||||
| #define SPDLOG_FILENAME_T(s) s | ||||
| SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) | ||||
| { | ||||
|     return filename; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| SPDLOG_INLINE int pid() | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     return static_cast<int>(::GetCurrentProcessId()); | ||||
| #else | ||||
|     return static_cast<int>(::getpid()); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // Determine if the terminal supports colors
 | ||||
| // Source: https://github.com/agauniyal/rang/
 | ||||
| SPDLOG_INLINE bool is_color_terminal() SPDLOG_NOEXCEPT | ||||
| { | ||||
| #ifdef _WIN32 | ||||
|     return true; | ||||
| #else | ||||
|     static constexpr const char *Terms[] = { | ||||
|         "ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", "linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm"}; | ||||
| 
 | ||||
|     const char *env_p = std::getenv("TERM"); | ||||
|     if (env_p == nullptr) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     static const bool result = | ||||
|         std::any_of(std::begin(Terms), std::end(Terms), [&](const char *term) { return std::strstr(env_p, term) != nullptr; }); | ||||
|     return result; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // Detrmine if the terminal attached
 | ||||
| // Source: https://github.com/agauniyal/rang/
 | ||||
| SPDLOG_INLINE bool in_terminal(FILE *file) SPDLOG_NOEXCEPT | ||||
| { | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     return _isatty(_fileno(file)) != 0; | ||||
| #else | ||||
|     return isatty(fileno(file)) != 0; | ||||
| #endif | ||||
| } | ||||
| } // namespace os
 | ||||
| } // namespace details
 | ||||
| } // namespace spdlog
 | ||||
							
								
								
									
										31
									
								
								src/sink.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/sink.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| #include "spdlog/common.h" | ||||
| #include "spdlog/details/pattern_formatter.h" | ||||
| 
 | ||||
| #ifndef SPDLOG_HEADER_ONLY | ||||
| #include "spdlog/sinks/sink.h" | ||||
| #endif | ||||
| 
 | ||||
| SPDLOG_INLINE spdlog::sinks::sink::sink() | ||||
|     : formatter_{details::make_unique<spdlog::pattern_formatter>()} | ||||
| {} | ||||
| 
 | ||||
| SPDLOG_INLINE spdlog::sinks::sink::sink(std::unique_ptr<spdlog::formatter> formatter) | ||||
|     : formatter_{std::move(formatter)} | ||||
| {} | ||||
| 
 | ||||
| SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const | ||||
| { | ||||
|     return msg_level >= level_.load(std::memory_order_relaxed); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level) | ||||
| { | ||||
|     level_.store(log_level); | ||||
| } | ||||
| 
 | ||||
| SPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const | ||||
| { | ||||
|     return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user