diff --git a/example/example.cpp b/example/example.cpp index 345f8bd1..b42c9440 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -7,229 +7,19 @@ // // -#include +#include "spdlog/logger.h" + + +namespace spdlog { +class logger; +} + +spdlog::logger *get_logger(); -void stdout_logger_example(); -void basic_example(); -void rotating_example(); -void daily_example(); -void async_example(); -void binary_example(); -void trace_example(); -void multi_sink_example(); -void user_defined_example(); -void err_handler_example(); -void syslog_example(); -void clone_example(); -#include "spdlog/spdlog.h" int main(int, char *[]) -{ - spdlog::info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH); - spdlog::warn("Easy padding in numbers like {:08d}", 12); - spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); - spdlog::info("Support for floats {:03.2f}", 1.23456); - spdlog::info("Positional args are {1} {0}..", "too", "supported"); - spdlog::info("{:>8} aligned, {:<8} aligned", "right", "left"); - - // Runtime log levels - spdlog::set_level(spdlog::level::info); // Set global log level to info - spdlog::debug("This message should not be displayed!"); - spdlog::set_level(spdlog::level::trace); // Set specific logger's log level - spdlog::debug("This message should be displayed.."); - - // Customize msg format for all loggers - spdlog::set_pattern("[%H:%M:%S %z] [%^%L%$] [thread %t] %v"); - spdlog::info("This an info message with custom format"); - spdlog::set_pattern("%+"); // back to default format - - try - { - stdout_logger_example(); - basic_example(); - rotating_example(); - daily_example(); - clone_example(); - async_example(); - binary_example(); - multi_sink_example(); - user_defined_example(); - err_handler_example(); - trace_example(); - - // Flush all *registered* loggers using a worker thread every 3 seconds. - // note: registered loggers *must* be thread safe for this to work correctly! - spdlog::flush_every(std::chrono::seconds(3)); - - // Apply some function on all registered loggers - spdlog::apply_all([&](std::shared_ptr l) { l->info("End of example."); }); - - // Release all spdlog resources, and drop all loggers in the registry. - // This is optional (only mandatory if using windows + async log). - spdlog::shutdown(); - } - - // Exceptions will only be thrown upon failed logger or sink construction (not during logging). - catch (const spdlog::spdlog_ex &ex) - { - std::printf("Log initialization failed: %s\n", ex.what()); - return 1; - } -} - -#include "spdlog/sinks/stdout_color_sinks.h" -// or #include "spdlog/sinks/stdout_sinks.h" if no colors needed. -void stdout_logger_example() -{ - // Create color multi threaded logger. - auto console = spdlog::stdout_color_mt("console"); - // or for stderr: - // auto console = spdlog::stderr_color_mt("error-logger"); -} - -#include "spdlog/sinks/basic_file_sink.h" -void basic_example() -{ - // Create basic file logger (not rotated). - auto my_logger = spdlog::basic_logger_mt("file_logger", "logs/basic-log.txt"); -} - -#include "spdlog/sinks/rotating_file_sink.h" -void rotating_example() -{ - // Create a file rotating logger with 5mb size max and 3 rotated files. - auto rotating_logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3); -} - -#include "spdlog/sinks/daily_file_sink.h" -void daily_example() -{ - // Create a daily logger - a new file is created every day on 2:30am. - auto daily_logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30); -} - -// Clone a logger and give it new name. -// Useful for creating component/subsystem loggers from some "root" logger. -void clone_example() -{ - auto network_logger = spdlog::default_logger()->clone("network"); - network_logger->info("Logging network stuff.."); -} - -#include "spdlog/async.h" -void async_example() -{ - // Default thread pool settings can be modified *before* creating the async logger: - // spdlog::init_thread_pool(32768, 1); // queue with max 32k items 1 backing thread. - auto async_file = spdlog::basic_logger_mt("async_file_logger", "logs/async_log.txt"); - // alternatively: - // auto async_file = spdlog::create_async("async_file_logger", "logs/async_log.txt"); - - for (int i = 1; i < 101; ++i) - { - async_file->info("Async message #{}", i); - } -} - -// Log binary data as hex. -// Many types of std::container types can be used. -// Iterator ranges are supported too. -// Format flags: -// {:X} - print in uppercase. -// {:s} - don't separate each byte with space. -// {:p} - don't print the position on each line start. -// {:n} - don't split the output to lines. - -#include "spdlog/fmt/bin_to_hex.h" -void binary_example() -{ - std::vector buf; - for (int i = 0; i < 80; i++) - { - buf.push_back(static_cast(i & 0xff)); - } - spdlog::info("Binary example: {}", spdlog::to_hex(buf)); - spdlog::info("Another binary example:{:n}", spdlog::to_hex(std::begin(buf), std::begin(buf) + 10)); - // more examples: - // logger->info("uppercase: {:X}", spdlog::to_hex(buf)); - // logger->info("uppercase, no delimiters: {:Xs}", spdlog::to_hex(buf)); - // logger->info("uppercase, no delimiters, no position info: {:Xsp}", spdlog::to_hex(buf)); -} - -// Compile time log levels. -// define SPDLOG_ACTIVE_LEVEL to required level (e.g. SPDLOG_LEVEL_TRACE) -void trace_example() -{ - // trace from default logger - SPDLOG_TRACE("Some trace message.. {} ,{}", 1, 3.23); - // debug from default logger - SPDLOG_DEBUG("Some debug message.. {} ,{}", 1, 3.23); - - // trace from logger object - auto logger = spdlog::get("file_logger"); - SPDLOG_LOGGER_TRACE(logger, "another trace message"); -} - -// A logger with multiple sinks (stdout and file) - each with a different format and log level. -void multi_sink_example() -{ - auto console_sink = std::make_shared(); - console_sink->set_level(spdlog::level::warn); - console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v"); - - auto file_sink = std::make_shared("logs/multisink.txt", true); - file_sink->set_level(spdlog::level::trace); - - spdlog::logger logger("multi_sink", {console_sink, file_sink}); - logger.set_level(spdlog::level::debug); - logger.warn("this should appear in both console and file"); - logger.info("this message should not appear in the console, only in the file"); -} - -// User defined types logging by implementing operator<< -#include "spdlog/fmt/ostr.h" // must be included -struct my_type -{ - int i; - template - friend OStream &operator<<(OStream &os, const my_type &c) - { - return os << "[my_type i=" << c.i << "]"; - } -}; - -void user_defined_example() -{ - spdlog::info("user defined type: {}", my_type{14}); -} - -// Custom error handler. Will be triggered on log failure. -void err_handler_example() -{ - // can be set globally or per logger(logger->set_error_handler(..)) - spdlog::set_error_handler([](const std::string &msg) { printf("*** Custom log error handler: %s ***\n", msg.c_str()); }); -} - -// syslog example (linux/osx/freebsd) -#ifndef _WIN32 -#include "spdlog/sinks/syslog_sink.h" -void syslog_example() -{ - std::string ident = "spdlog-example"; - auto syslog_logger = spdlog::syslog_logger_mt("syslog", ident, LOG_PID); - syslog_logger->warn("This is warning that will end up in syslog."); -} -#endif - -// Android example. -#if defined(__ANDROID__) -#include "spdlog/sinks/android_sink.h" -void android_example() -{ - std::string tag = "spdlog-android"; - auto android_logger = spdlog::android_logger_mt("android", tag); - android_logger->critical("Use \"adb shell logcat\" to view this message."); -} - -#endif +{ + auto *l = get_logger(); + l->info("HELLO"); +} \ No newline at end of file diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index d44652b5..80245ba1 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -10,426 +10,426 @@ #include #include -#define SPDLOG_CATCH_AND_HANDLE \ - catch (const std::exception &ex) \ - { \ - err_handler_(ex.what()); \ - } \ - catch (...) \ - { \ - err_handler_("Unknown exception in logger"); \ - } +//#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 -inline spdlog::logger::logger(std::string logger_name, It begin, It end) - : name_(std::move(logger_name)) - , sinks_(begin, end) -{ -} +//template +//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 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(std::string logger_name, spdlog::sink_ptr single_sink) +// : logger(std::move(logger_name), {std::move(single_sink)}) +//{ +//} -inline spdlog::logger::~logger() = default; +//inline spdlog::logger::~logger() = default; -inline void spdlog::logger::set_formatter(std::unique_ptr f) -{ - for (auto &sink : sinks_) - { - sink->set_formatter(f->clone()); - } -} +//inline void spdlog::logger::set_formatter(std::unique_ptr 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(std::move(pattern), time_type); - set_formatter(std::move(new_formatter)); -} +//inline void spdlog::logger::set_pattern(std::string pattern, pattern_time_type time_type) +//{ +// auto new_formatter = details::make_unique(std::move(pattern), time_type); +// set_formatter(std::move(new_formatter)); +//} -template -inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const char *fmt, const Args &... args) -{ - if (!should_log(lvl)) - { - return; - } +//template +//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 +//} - 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 +//inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Args &... args) +//{ +// log(source_loc{}, lvl, fmt, args...); +//} -template -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(source_loc source, level::level_enum lvl, const char *msg) -{ - if (!should_log(lvl)) - { - return; - } +//inline void spdlog::logger::log(level::level_enum lvl, const char *msg) +//{ +// log(source_loc{}, lvl, msg); +//} - try - { - details::log_msg log_msg(source, &name_, lvl, spdlog::string_view_t(msg)); - sink_it_(log_msg); - } - SPDLOG_CATCH_AND_HANDLE -} +//template +//inline void spdlog::logger::log(level::level_enum lvl, const T &msg) +//{ +// log(source_loc{}, lvl, msg); +//} +// +//template::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 +//} -inline void spdlog::logger::log(level::level_enum lvl, const char *msg) -{ - log(source_loc{}, lvl, msg); -} +//template::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 -inline void spdlog::logger::log(level::level_enum lvl, const T &msg) -{ - log(source_loc{}, lvl, msg); -} +//template +//inline void spdlog::logger::trace(const char *fmt, const Args &... args) +//{ +// log(level::trace, fmt, args...); +//} +// +//template +//inline void spdlog::logger::debug(const char *fmt, const Args &... args) +//{ +// log(level::debug, fmt, args...); +//} +// +//template +//inline void spdlog::logger::info(const char *fmt, const Args &... args) +//{ +// log(level::info, fmt, args...); +//} +// +//template +//inline void spdlog::logger::warn(const char *fmt, const Args &... args) +//{ +// log(level::warn, fmt, args...); +//} +// +//template +//inline void spdlog::logger::error(const char *fmt, const Args &... args) +//{ +// log(level::err, fmt, args...); +//} +// +//template +//inline void spdlog::logger::critical(const char *fmt, const Args &... args) +//{ +// log(level::critical, fmt, args...); +//} +// +//template +//inline void spdlog::logger::trace(const T &msg) +//{ +// log(level::trace, msg); +//} +// +//template +//inline void spdlog::logger::debug(const T &msg) +//{ +// log(level::debug, msg); +//} +// +//template +//inline void spdlog::logger::info(const T &msg) +//{ +// log(level::info, msg); +//} +// +//template +//inline void spdlog::logger::warn(const T &msg) +//{ +// log(level::warn, msg); +//} +// +//template +//inline void spdlog::logger::error(const T &msg) +//{ +// log(level::err, msg); +//} +// +//template +//inline void spdlog::logger::critical(const T &msg) +//{ +// log(level::critical, msg); +//} -template::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 -} +//#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT -template::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 -} +//inline void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target) +//{ +// int wbuf_size = static_cast(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 -inline void spdlog::logger::trace(const char *fmt, const Args &... args) -{ - log(level::trace, fmt, args...); -} +//template +//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 -inline void spdlog::logger::debug(const char *fmt, const Args &... args) -{ - log(level::debug, fmt, args...); -} - -template -inline void spdlog::logger::info(const char *fmt, const Args &... args) -{ - log(level::info, fmt, args...); -} - -template -inline void spdlog::logger::warn(const char *fmt, const Args &... args) -{ - log(level::warn, fmt, args...); -} - -template -inline void spdlog::logger::error(const char *fmt, const Args &... args) -{ - log(level::err, fmt, args...); -} - -template -inline void spdlog::logger::critical(const char *fmt, const Args &... args) -{ - log(level::critical, fmt, args...); -} - -template -inline void spdlog::logger::trace(const T &msg) -{ - log(level::trace, msg); -} - -template -inline void spdlog::logger::debug(const T &msg) -{ - log(level::debug, msg); -} - -template -inline void spdlog::logger::info(const T &msg) -{ - log(level::info, msg); -} - -template -inline void spdlog::logger::warn(const T &msg) -{ - log(level::warn, msg); -} - -template -inline void spdlog::logger::error(const T &msg) -{ - log(level::err, msg); -} - -template -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(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 -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 -inline void spdlog::logger::log(level::level_enum lvl, const wchar_t *fmt, const Args &... args) -{ - log(source_loc{}, lvl, fmt, args...); -} - -template -inline void spdlog::logger::trace(const wchar_t *fmt, const Args &... args) -{ - log(level::trace, fmt, args...); -} - -template -inline void spdlog::logger::debug(const wchar_t *fmt, const Args &... args) -{ - log(level::debug, fmt, args...); -} - -template -inline void spdlog::logger::info(const wchar_t *fmt, const Args &... args) -{ - log(level::info, fmt, args...); -} - -template -inline void spdlog::logger::warn(const wchar_t *fmt, const Args &... args) -{ - log(level::warn, fmt, args...); -} - -template -inline void spdlog::logger::error(const wchar_t *fmt, const Args &... args) -{ - log(level::err, fmt, args...); -} - -template -inline void spdlog::logger::critical(const wchar_t *fmt, const Args &... args) -{ - log(level::critical, fmt, args...); -} - -#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT +//template +//inline void spdlog::logger::log(level::level_enum lvl, const wchar_t *fmt, const Args &... args) +//{ +// log(source_loc{}, lvl, fmt, args...); +//} +// +//template +//inline void spdlog::logger::trace(const wchar_t *fmt, const Args &... args) +//{ +// log(level::trace, fmt, args...); +//} +// +//template +//inline void spdlog::logger::debug(const wchar_t *fmt, const Args &... args) +//{ +// log(level::debug, fmt, args...); +//} +// +//template +//inline void spdlog::logger::info(const wchar_t *fmt, const Args &... args) +//{ +// log(level::info, fmt, args...); +//} +// +//template +//inline void spdlog::logger::warn(const wchar_t *fmt, const Args &... args) +//{ +// log(level::warn, fmt, args...); +//} +// +//template +//inline void spdlog::logger::error(const wchar_t *fmt, const Args &... args) +//{ +// log(level::err, fmt, args...); +//} +// +//template +//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 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_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 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 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() +//{ +// try +// { +// flush_(); +// } +// SPDLOG_CATCH_AND_HANDLE +//} -inline void spdlog::logger::flush_on(level::level_enum log_level) -{ - flush_level_.store(log_level); -} +//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(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::flush_level() const -{ - return static_cast(flush_level_.load(std::memory_order_relaxed)); -} +//inline spdlog::level::level_enum spdlog::logger::default_level() +//{ +// return static_cast(SPDLOG_ACTIVE_LEVEL); +//} -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::level() const +//{ +// return static_cast(level_.load(std::memory_order_relaxed)); +//} -inline spdlog::level::level_enum spdlog::logger::default_level() -{ - return static_cast(SPDLOG_ACTIVE_LEVEL); -} - -inline spdlog::level::level_enum spdlog::logger::level() const -{ - return static_cast(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); -} +//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); - } - } +//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_(); +// } +//} - if (should_flush_(msg)) - { - flush_(); - } -} +//inline void spdlog::logger::flush_() +//{ +// for (auto &sink : sinks_) +// { +// sink->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::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::logger::sinks() const +//{ +// return sinks_; +//} -inline void spdlog::logger::incr_msg_counter_(details::log_msg &msg) -{ - msg.msg_id = msg_counter_.fetch_add(1, std::memory_order_relaxed); -} +//inline std::vector &spdlog::logger::sinks() +//{ +// return sinks_; +//} -inline const std::vector &spdlog::logger::sinks() const -{ - return sinks_; -} - -inline std::vector &spdlog::logger::sinks() -{ - return sinks_; -} - -inline std::shared_ptr spdlog::logger::clone(std::string logger_name) -{ - auto cloned = std::make_shared(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; -} +//inline std::shared_ptr spdlog::logger::clone(std::string logger_name) +//{ +// auto cloned = std::make_shared(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; +//} diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index ec06828f..446a5076 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -21,154 +21,455 @@ #include "spdlog/common.h" #include "spdlog/formatter.h" #include "spdlog/sinks/sink.h" +#include "spdlog/details/fmt_helper.h" #include #include #include +#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 { public: - logger(std::string name, sink_ptr single_sink); - logger(std::string name, sinks_init_list sinks); - + template - logger(std::string name, It begin, It end); + logger(std::string name, It begin, It end) + : name_(std::move(name)) + , sinks_(begin, end) + {} - virtual ~logger(); + 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 - void log(level::level_enum lvl, const char *fmt, const Args &... args); + template + void log(source_loc loc, 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(loc, &name_, lvl, to_string_view(buf)); + sink_it_(log_msg); + } + SPDLOG_CATCH_AND_HANDLE + } template - void log(source_loc loc, level::level_enum lvl, const char *fmt, const Args &... args); + void log(level::level_enum lvl, const char *fmt, const Args &... args) + { + log(source_loc{}, lvl, fmt, args...); + } - void log(level::level_enum lvl, const char *msg); + + void log(source_loc loc, level::level_enum lvl, const char *msg) + { + if (!should_log(lvl)) + { + return; + } - void log(source_loc loc, level::level_enum lvl, const char *msg); + try + { + details::log_msg log_msg(loc, &name_, lvl, spdlog::string_view_t(msg)); + sink_it_(log_msg); + } + SPDLOG_CATCH_AND_HANDLE + } + + void log(level::level_enum lvl, const char *msg) + { + log(source_loc{}, lvl, msg); + } + + template - void trace(const char *fmt, const Args &... args); + void trace(const char *fmt, const Args &... args) + { + log(level::trace, fmt, args...); + } + template - void debug(const char *fmt, const Args &... args); + void debug(const char *fmt, const Args &... args) + { + log(level::debug, fmt, args...); + } + template - void info(const char *fmt, const Args &... args); + void info(const char *fmt, const Args &... args) + { + log(level::info, fmt, args...); + } template - void warn(const char *fmt, const Args &... args); + void warn(const char *fmt, const Args &... args) + { + log(level::warn, fmt, args...); + } template - void error(const char *fmt, const Args &... args); + void error(const char *fmt, const Args &... args) + { + log(level::err, fmt, args...); + } template - void critical(const char *fmt, const Args &... 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 - template - void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args); + inline void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target) + { + int wbuf_size = static_cast(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 + 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 - void log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args); + void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args) + { + log(source_loc{}, lvl, fmt, args...); + } + + template + void trace(const wchar_t *fmt, const Args &... args) + { + log(level::trace, fmt, args...); + } template - void trace(const wchar_t *fmt, const Args &... args); + void debug(const wchar_t *fmt, const Args &... args) + { + log(level::debug, fmt, args...); + } template - void debug(const wchar_t *fmt, const Args &... args); + void info(const wchar_t *fmt, const Args &... args) + { + log(level::info, fmt, args...); + } template - void info(const wchar_t *fmt, const Args &... args); + void warn(const wchar_t *fmt, const Args &... args) + { + log(level::warn, fmt, args...); + } template - void warn(const wchar_t *fmt, const Args &... args); + void error(const wchar_t *fmt, const Args &... args) + { + log(level::err, fmt, args...); + } template - void error(const wchar_t *fmt, const Args &... args); - - template - void critical(const wchar_t *fmt, const Args &... args); + void critical(const wchar_t *fmt, const Args &... args) + { + log(level::critical, fmt, args...); + } #endif // _WIN32 #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT - template - void log(level::level_enum lvl, const T &); + template + void log(level::level_enum lvl, const T &msg) + { + log(source_loc{}, lvl, msg); + } // T can be statically converted to string_view template::value, T>::type * = nullptr> - void log(source_loc loc, level::level_enum lvl, const T &); + 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::value, T>::type * = nullptr> - void log(source_loc loc, level::level_enum lvl, const T &); + 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 - void trace(const T &msg); + void trace(const T &msg) + { + log(level::trace, msg); + } template - void debug(const T &msg); + void debug(const T &msg) + { + log(level::debug, msg); + } template - void info(const T &msg); + void info(const T &msg) + { + log(level::info, msg); + } template - void warn(const T &msg); + void warn(const T &msg) + { + log(level::warn, msg); + } template - void error(const T &msg); + void error(const T &msg) + { + log(level::err, msg); + } template - void critical(const T &msg); + 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); + bool should_log(level::level_enum msg_level) const + { + return msg_level >= level_.load(std::memory_order_relaxed); + } - static level::level_enum default_level(); - level::level_enum level() const; - const std::string &name() const; + void set_level(level::level_enum log_level) + { + level_.store(log_level); + } + + static level::level_enum default_level() + { + return static_cast(SPDLOG_ACTIVE_LEVEL); + } + + level::level_enum level() const + { + return static_cast(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); - void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local); + void set_formatter(std::unique_ptr 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(std::move(pattern), time_type); + set_formatter(std::move(new_formatter)); + } // flush functions - void flush(); - void flush_on(level::level_enum log_level); - level::level_enum flush_level() const; + 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(flush_level_.load(std::memory_order_relaxed)); + } // sinks - const std::vector &sinks() const; - std::vector &sinks(); + const std::vector &sinks() const + { + return sinks_; + } + + std::vector &sinks() + { + return sinks_; + } // error handler - void set_error_handler(log_err_handler err_handler); - log_err_handler error_handler() const; + 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 clone(std::string logger_name); + virtual std::shared_ptr clone(std::string logger_name) + { + auto cloned = std::make_shared(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); - virtual void flush_(); + 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)) + { + sink->log(msg); + } + } - bool should_flush_(const details::log_msg &msg); + if (should_flush_(msg)) + { + flush_(); + } + } + + virtual void flush_() + { + for (auto &sink : sinks_) + { + sink->flush(); + } + } + + 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); + void 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); + } // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)) - void incr_msg_counter_(details::log_msg &msg); + void incr_msg_counter_(details::log_msg &msg) + { + msg.msg_id = msg_counter_.fetch_add(1, std::memory_order_relaxed); + } const std::string name_; std::vector sinks_; @@ -180,4 +481,3 @@ protected: }; } // namespace spdlog -#include "details/logger_impl.h"