From b368d18b0f2afd6b228bfbf0128fb54ad51541de Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 12 Oct 2018 03:04:55 +0300 Subject: [PATCH] Added default logger API --- .clang-format | 2 +- CMakeLists.txt | 2 +- bench/async_bench.cpp | 3 +- bench/bench.cpp | 3 +- bench/latency.cpp | 4 +- example/example.cpp | 146 ++++++++---------- example/multisink.cpp | 3 +- include/spdlog/default_logger.h | 0 include/spdlog/details/os.h | 2 +- include/spdlog/details/pattern_formatter.h | 11 +- include/spdlog/details/registry.h | 38 +++++ include/spdlog/sinks/android_sink.h | 4 + include/spdlog/sinks/ansicolor_sink.h | 4 + include/spdlog/sinks/basic_file_sink.h | 6 +- include/spdlog/sinks/daily_file_sink.h | 6 +- include/spdlog/sinks/dist_sink.h | 4 + include/spdlog/sinks/msvc_sink.h | 4 + include/spdlog/sinks/null_sink.h | 17 ++ include/spdlog/sinks/ostream_sink.h | 4 + include/spdlog/sinks/rotating_file_sink.h | 6 +- include/spdlog/sinks/stdout_color_sinks.h | 5 +- include/spdlog/sinks/stdout_sinks.h | 5 +- include/spdlog/sinks/syslog_sink.h | 5 +- include/spdlog/sinks/wincolor_sink.h | 4 + include/spdlog/spdlog.h | 171 +++++++++++++++++++-- include/spdlog/version.h | 2 +- tests/includes.h | 2 +- tests/registry.cpp | 23 +-- tests/test_misc.cpp | 39 +++++ 29 files changed, 406 insertions(+), 119 deletions(-) delete mode 100644 include/spdlog/default_logger.h diff --git a/.clang-format b/.clang-format index 89e5b902..aa95f7a5 100644 --- a/.clang-format +++ b/.clang-format @@ -88,7 +88,7 @@ PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right ReflowComments: true -SortIncludes: true +SortIncludes: false SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: false diff --git a/CMakeLists.txt b/CMakeLists.txt index fc753463..1dc01f87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ # cmake_minimum_required(VERSION 3.1) -project(spdlog VERSION 1.2.0 LANGUAGES CXX) +project(spdlog VERSION 1.3.0 LANGUAGES CXX) include(CTest) include(CMakeDependentOption) include(GNUInstallDirs) diff --git a/bench/async_bench.cpp b/bench/async_bench.cpp index 8d1e0edc..49a6f2f9 100644 --- a/bench/async_bench.cpp +++ b/bench/async_bench.cpp @@ -6,10 +6,11 @@ // // bench.cpp : spdlog benchmarks // +#include "spdlog/spdlog.h" #include "spdlog/async.h" #include "spdlog/sinks/basic_file_sink.h" #include "spdlog/sinks/stdout_color_sinks.h" -#include "spdlog/spdlog.h" + #include "utils.h" #include #include diff --git a/bench/bench.cpp b/bench/bench.cpp index 02826d04..61e9fcb3 100644 --- a/bench/bench.cpp +++ b/bench/bench.cpp @@ -6,12 +6,13 @@ // // bench.cpp : spdlog benchmarks // +#include "spdlog/spdlog.h" #include "spdlog/async.h" #include "spdlog/sinks/basic_file_sink.h" #include "spdlog/sinks/daily_file_sink.h" #include "spdlog/sinks/null_sink.h" #include "spdlog/sinks/rotating_file_sink.h" -#include "spdlog/spdlog.h" + #include "utils.h" #include #include // EXIT_FAILURE diff --git a/bench/latency.cpp b/bench/latency.cpp index dcc6965c..a696276a 100644 --- a/bench/latency.cpp +++ b/bench/latency.cpp @@ -6,12 +6,14 @@ // // latency.cpp : spdlog latency benchmarks // + +#include "spdlog/spdlog.h" #include "spdlog/async.h" #include "spdlog/sinks/basic_file_sink.h" #include "spdlog/sinks/daily_file_sink.h" #include "spdlog/sinks/null_sink.h" #include "spdlog/sinks/rotating_file_sink.h" -#include "spdlog/spdlog.h" + #include "utils.h" #include #include diff --git a/example/example.cpp b/example/example.cpp index 372ca14c..006fc2fe 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -7,141 +7,123 @@ // // -#include +#include -void stdout_example(); +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(); +#define SPDLOG_TRACE_ON +#define SPDLOG_DEBUG_ON #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 { - // console logging example - stdout_example(); - - // various file loggers + stdout_logger_example(); basic_example(); rotating_example(); daily_example(); - clone_example(); - - // async logging using a backing thread pool async_example(); - - // log binary data binary_example(); - - // a logger can have multiple targets with different formats multi_sink_example(); - - // user defined types logging by implementing operator<< user_defined_example(); - - // custom error handler err_handler_example(); + trace_example(); - // flush all *registered* loggers using a worker thread every 3 seconds. + // 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 + // Apply some function on all registered loggers spdlog::apply_all([&](std::shared_ptr l) { l->info("End of example."); }); - // release any threads created by spdlog, and drop all loggers in the registry. + // 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) + + // Exceptions will only be thrown upon failed logger or sink construction (not during logging). catch (const spdlog::spdlog_ex &ex) { - std::cout << "Log init failed: " << ex.what() << std::endl; + 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_example() +// or #include "spdlog/sinks/stdout_sinks.h" if no colors needed. +void stdout_logger_example() { - // create color multi threaded logger + // Create color multi threaded logger. auto console = spdlog::stdout_color_mt("console"); - console->info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH); - console->error("Some error message with arg: {}", 1); - - auto err_logger = spdlog::stderr_color_mt("stderr"); - err_logger->error("Some error message"); - - // Formatting examples - console->warn("Easy padding in numbers like {:08d}", 12); - console->critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); - console->info("Support for floats {:03.2f}", 1.23456); - console->info("Positional args are {1} {0}..", "too", "supported"); - console->info("{:<30}", "left aligned"); - - spdlog::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)"); - - // Runtime log levels - spdlog::set_level(spdlog::level::info); // Set global log level to info - console->debug("This message should not be displayed!"); - console->set_level(spdlog::level::trace); // Set specific logger's log level - console->debug("This message should be displayed.."); - - // Customize msg format for all loggers - spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v"); - console->info("This an info message with custom format"); - spdlog::set_pattern("%+"); // back to default format - - // Compile time log levels - // define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON - SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23); - SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23); + // 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("basic_logger", "logs/basic-log.txt"); + // 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 + // 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 + // 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 +// 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::get("console")->clone("network"); + auto network_logger = spdlog::get()->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: + // 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: @@ -153,10 +135,10 @@ void async_example() } } -// log binary data as hex. -// many types of std::container types can be used. -// ranges are supported too. -// format flags: +// 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. @@ -165,19 +147,25 @@ void async_example() #include "spdlog/fmt/bin_to_hex.h" void binary_example() { - auto console = spdlog::get("console"); std::array buf; - console->info("Binary example: {}", spdlog::to_hex(buf)); - console->info("Another binary example:{:n}", spdlog::to_hex(std::begin(buf), std::begin(buf) + 10)); + 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)); } -// create logger with 2 targets with different log levels and formats -// the console will show only warnings or errors, while the file will log all +// Compile time log levels. +// Must define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON to turn them on. +void trace_example() +{ + auto logger = spdlog::get(); + SPDLOG_TRACE(logger, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23); + SPDLOG_DEBUG(logger, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23); +} +// 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(); @@ -192,7 +180,8 @@ void multi_sink_example() 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<< + +// User defined types logging by implementing operator<< #include "spdlog/fmt/ostr.h" // must be included struct my_type { @@ -206,17 +195,14 @@ struct my_type void user_defined_example() { - spdlog::get("console")->info("user defined type: {}", my_type{14}); + spdlog::info("user defined type: {}", my_type{14}); } -// -// custom error handler -// +// 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) { spdlog::get("console")->error("*** ERROR HANDLER EXAMPLE ***: {}", msg); }); - spdlog::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3); + spdlog::set_error_handler([](const std::string &msg) { printf("*** Custom log error handler: %s ***\n", msg.c_str()); }); } // syslog example (linux/osx/freebsd) @@ -230,7 +216,7 @@ void syslog_example() } #endif -// Android example +// Android example. #if defined(__ANDROID__) #include "spdlog/sinks/android_sink.h" void android_example() diff --git a/example/multisink.cpp b/example/multisink.cpp index 7dc267d2..fd79231c 100644 --- a/example/multisink.cpp +++ b/example/multisink.cpp @@ -1,6 +1,7 @@ +#include "spdlog/spdlog.h" #include "spdlog/sinks/basic_file_sink.h" #include "spdlog/sinks/stdout_sinks.h" -#include "spdlog/spdlog.h" + #include #include diff --git a/include/spdlog/default_logger.h b/include/spdlog/default_logger.h deleted file mode 100644 index e69de29b..00000000 diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h index aa802abb..23e011be 100644 --- a/include/spdlog/details/os.h +++ b/include/spdlog/details/os.h @@ -185,7 +185,7 @@ inline int rename(const filename_t &filename1, const filename_t &filename2) SPDL } // Return if file exists -inline bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT +inline bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT { #ifdef _WIN32 #ifdef SPDLOG_WCHAR_FILENAMES diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 14fb124c..a35564be 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -508,10 +508,13 @@ class full_formatter final : public flag_formatter #endif #ifndef SPDLOG_NO_NAME - dest.push_back('['); - fmt_helper::append_str(*msg.logger_name, dest); - dest.push_back(']'); - dest.push_back(' '); + if (!msg.logger_name->empty()) + { + dest.push_back('['); + fmt_helper::append_str(*msg.logger_name, dest); + dest.push_back(']'); + dest.push_back(' '); + } #endif dest.push_back('['); diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 63baf748..9896d6f3 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -14,6 +14,14 @@ #include "spdlog/details/periodic_worker.h" #include "spdlog/logger.h" +// support for the default stdout color logger +#ifdef _WIN32 +#include "spdlog/sinks/wincolor_sink.h" +#else +#include "spdlog/sinks/ansicolor_sink.h" + +#endif + #include #include #include @@ -66,6 +74,25 @@ public: return found == loggers_.end() ? nullptr : found->second; } + std::shared_ptr get_default_logger() const + { + return default_logger_; + } + + // set default logger. + // default logger is stored in default_logger_ (for faster retrieval) and in the map of existing loggers. + void set_default_logger(std::shared_ptr new_default_logger) + { + std::lock_guard lock(logger_map_mutex_); + // remove previous default logger from the map + if (default_logger_ != nullptr) + { + loggers_.erase(default_logger_->name()); + } + loggers_[new_default_logger->name()] = new_default_logger; + default_logger_ = std::move(new_default_logger); + } + void set_tp(std::shared_ptr tp) { std::lock_guard lock(tp_mutex_); @@ -154,6 +181,7 @@ public: { std::lock_guard lock(logger_map_mutex_); loggers_.clear(); + default_logger_.reset(); } // clean all reasources and threads started by the registry @@ -187,6 +215,15 @@ private: registry() : formatter_(new pattern_formatter("%+")) { + // create default logger (stdout_color_mt). +#ifdef _WIN32 + auto color_sink = std::make_shared(); +#else + auto color_sink = std::make_shared(); +#endif + SPDLOG_CONSTEXPR const char *default_logger_name = ""; + default_logger_ = std::make_shared(default_logger_name, std::move(color_sink)); + loggers_[default_logger_name] = default_logger_; } ~registry() = default; @@ -208,6 +245,7 @@ private: log_err_handler err_handler_; std::shared_ptr tp_; std::unique_ptr periodic_flusher_; + std::shared_ptr default_logger_; }; } // namespace details diff --git a/include/spdlog/sinks/android_sink.h b/include/spdlog/sinks/android_sink.h index 44bbbf8c..8c3383c1 100644 --- a/include/spdlog/sinks/android_sink.h +++ b/include/spdlog/sinks/android_sink.h @@ -5,6 +5,10 @@ #pragma once +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "spdlog/details/fmt_helper.h" #include "spdlog/details/null_mutex.h" #include "spdlog/details/os.h" diff --git a/include/spdlog/sinks/ansicolor_sink.h b/include/spdlog/sinks/ansicolor_sink.h index ba94c3c8..bb2a2a12 100644 --- a/include/spdlog/sinks/ansicolor_sink.h +++ b/include/spdlog/sinks/ansicolor_sink.h @@ -5,6 +5,10 @@ #pragma once +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "spdlog/details/console_globals.h" #include "spdlog/details/null_mutex.h" #include "spdlog/details/os.h" diff --git a/include/spdlog/sinks/basic_file_sink.h b/include/spdlog/sinks/basic_file_sink.h index 3832efd5..0ab884aa 100644 --- a/include/spdlog/sinks/basic_file_sink.h +++ b/include/spdlog/sinks/basic_file_sink.h @@ -4,10 +4,14 @@ // #pragma once + +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "spdlog/details/file_helper.h" #include "spdlog/details/null_mutex.h" #include "spdlog/sinks/base_sink.h" -#include "spdlog/spdlog.h" #include #include diff --git a/include/spdlog/sinks/daily_file_sink.h b/include/spdlog/sinks/daily_file_sink.h index 70a290be..376a1ab0 100644 --- a/include/spdlog/sinks/daily_file_sink.h +++ b/include/spdlog/sinks/daily_file_sink.h @@ -4,11 +4,15 @@ // #pragma once + +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "spdlog/details/file_helper.h" #include "spdlog/details/null_mutex.h" #include "spdlog/fmt/fmt.h" #include "spdlog/sinks/base_sink.h" -#include "spdlog/spdlog.h" #include #include diff --git a/include/spdlog/sinks/dist_sink.h b/include/spdlog/sinks/dist_sink.h index 0d8533eb..8ed41f1a 100644 --- a/include/spdlog/sinks/dist_sink.h +++ b/include/spdlog/sinks/dist_sink.h @@ -5,6 +5,10 @@ #pragma once +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "base_sink.h" #include "spdlog/details/log_msg.h" #include "spdlog/details/null_mutex.h" diff --git a/include/spdlog/sinks/msvc_sink.h b/include/spdlog/sinks/msvc_sink.h index a0284960..c8e60be7 100644 --- a/include/spdlog/sinks/msvc_sink.h +++ b/include/spdlog/sinks/msvc_sink.h @@ -5,6 +5,10 @@ #pragma once +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #if defined(_WIN32) #include "spdlog/details/null_mutex.h" diff --git a/include/spdlog/sinks/null_sink.h b/include/spdlog/sinks/null_sink.h index 73b8c2b7..57adfa33 100644 --- a/include/spdlog/sinks/null_sink.h +++ b/include/spdlog/sinks/null_sink.h @@ -5,6 +5,10 @@ #pragma once +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "spdlog/details/null_mutex.h" #include "spdlog/sinks/base_sink.h" @@ -25,4 +29,17 @@ using null_sink_mt = null_sink; using null_sink_st = null_sink; } // namespace sinks + +template +inline std::shared_ptr null_logger_mt(const std::string &logger_name) +{ + return Factory::template create(logger_name); +} + +template +inline std::shared_ptr null_logger_st(const std::string &logger_name) +{ + return Factory::template create(logger_name); +} + } // namespace spdlog diff --git a/include/spdlog/sinks/ostream_sink.h b/include/spdlog/sinks/ostream_sink.h index 5649b0b8..b28802a0 100644 --- a/include/spdlog/sinks/ostream_sink.h +++ b/include/spdlog/sinks/ostream_sink.h @@ -5,6 +5,10 @@ #pragma once +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "spdlog/details/null_mutex.h" #include "spdlog/sinks/base_sink.h" diff --git a/include/spdlog/sinks/rotating_file_sink.h b/include/spdlog/sinks/rotating_file_sink.h index 6fc1627c..adf12b6f 100644 --- a/include/spdlog/sinks/rotating_file_sink.h +++ b/include/spdlog/sinks/rotating_file_sink.h @@ -4,11 +4,15 @@ // #pragma once + +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "spdlog/details/file_helper.h" #include "spdlog/details/null_mutex.h" #include "spdlog/fmt/fmt.h" #include "spdlog/sinks/base_sink.h" -#include "spdlog/spdlog.h" #include #include diff --git a/include/spdlog/sinks/stdout_color_sinks.h b/include/spdlog/sinks/stdout_color_sinks.h index 761e32a4..f0475692 100644 --- a/include/spdlog/sinks/stdout_color_sinks.h +++ b/include/spdlog/sinks/stdout_color_sinks.h @@ -5,7 +5,10 @@ #pragma once -#include "spdlog/spdlog.h" +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #ifdef _WIN32 #include "spdlog/sinks/wincolor_sink.h" #else diff --git a/include/spdlog/sinks/stdout_sinks.h b/include/spdlog/sinks/stdout_sinks.h index 00c6ddd1..efbbaaac 100644 --- a/include/spdlog/sinks/stdout_sinks.h +++ b/include/spdlog/sinks/stdout_sinks.h @@ -5,9 +5,12 @@ #pragma once +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "spdlog/details/console_globals.h" #include "spdlog/details/null_mutex.h" -#include "spdlog/spdlog.h" #include #include diff --git a/include/spdlog/sinks/syslog_sink.h b/include/spdlog/sinks/syslog_sink.h index 151e7a11..cb76613d 100644 --- a/include/spdlog/sinks/syslog_sink.h +++ b/include/spdlog/sinks/syslog_sink.h @@ -5,8 +5,11 @@ #pragma once +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "spdlog/sinks/base_sink.h" -#include "spdlog/spdlog.h" #include #include diff --git a/include/spdlog/sinks/wincolor_sink.h b/include/spdlog/sinks/wincolor_sink.h index 77c50a83..6e2b0122 100644 --- a/include/spdlog/sinks/wincolor_sink.h +++ b/include/spdlog/sinks/wincolor_sink.h @@ -5,6 +5,10 @@ #pragma once +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + #include "spdlog/common.h" #include "spdlog/details/console_globals.h" #include "spdlog/details/null_mutex.h" diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index ff9a77a9..3158909a 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -14,8 +14,6 @@ #include "spdlog/logger.h" #include "spdlog/version.h" -#include "spdlog/default_logger.h" - #include #include #include @@ -128,19 +126,173 @@ inline void shutdown() details::registry::instance().shutdown(); } -/////////////////////////////////////////////////////////////////////////////// // -// Trace & Debug can be switched on/off at compile time for zero cost debug -// statements. +// API for using default logger (stdout_color_mt), +// e.g: spdlog::info("Message {}", 1); +// +// The default logger object can be accessed using the spdlog::get(): +// For example, to add another sink to it: +// spdlog::get()->sinks()->push_back(some_sink); +// +// The default logger can replaced using spdlog::set_default_logger(new_logger). +// For example, to replace it with a file logger: +// spdlog::set_default_logger(std::move(spdlog::basic_logger_st("mylog.txt")); +// + +// Return the default logger +// inline std::shared_ptr get() +//{ +// return details::registry::instance().get_default_logger(); +//} + +inline std::shared_ptr get() +{ + return details::registry::instance().get_default_logger(); +} + +inline void set_default_logger(std::shared_ptr default_logger) +{ + details::registry::instance().set_default_logger(std::move(default_logger)); +} + +template +inline void log(level::level_enum lvl, const char *fmt, const Args &... args) +{ + get()->log(lvl, fmt, args...); +} + +template +inline void trace(const char *fmt, const Args &... args) +{ + get()->trace(fmt, args...); +} + +template +inline void debug(const char *fmt, const Args &... args) +{ + get()->debug(fmt, args...); +} + +template +inline void info(const char *fmt, const Args &... args) +{ + get()->info(fmt, args...); +} + +template +inline void warn(const char *fmt, const Args &... args) +{ + get()->warn(fmt, args...); +} + +template +inline void error(const char *fmt, const Args &... args) +{ + get()->error(fmt, args...); +} + +template +inline void critical(const char *fmt, const Args &... args) +{ + get()->critical(fmt, args...); +} + +template +inline void log(level::level_enum lvl, const T &msg) +{ + get()->log(lvl, msg); +} + +template +inline void trace(const T &msg) +{ + get()->trace(msg); +} + +template +inline void debug(const T &msg) +{ + get()->debug(msg); +} + +template +inline void info(const T &msg) +{ + get()->info(msg); +} + +template +inline void warn(const T &msg) +{ + get()->warn(msg); +} + +template +inline void error(const T &msg) +{ + get()->error(msg); +} + +template +inline void critical(const T &msg) +{ + get()->critical(msg); +} + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT +template +inline void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args) +{ + get()->log(lvl, fmt, args...); +} + +template +inline void trace(const wchar_t *fmt, const Args &... args) +{ + get()->trace(fmt, args...); +} + +template +inline void debug(const wchar_t *fmt, const Args &... args) +{ + get()->debug(fmt, args...); +} + +template +inline void info(const wchar_t *fmt, const Args &... args) +{ + get()->info(fmt, args...); +} + +template +inline void warn(const wchar_t *fmt, const Args &... args) +{ + get()->warn(fmt, args...); +} + +template +inline void error(const wchar_t *fmt, const Args &... args) +{ + get()->error(fmt, args...); +} + +template +inline void critical(const wchar_t *fmt, const Args &... args) +{ + get()->critical(fmt, args...); +} + +#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT + +// +// Trace & Debug can be switched on/off at compile time with zero cost. // Uncomment SPDLOG_DEBUG_ON/SPDLOG_TRACE_ON in tweakme.h to enable. // SPDLOG_TRACE(..) will also print current file and line. // // Example: // spdlog::set_level(spdlog::level::trace); -// SPDLOG_TRACE(my_logger, "some trace message"); // SPDLOG_TRACE(my_logger, "another trace message {} {}", 1, 2); -// SPDLOG_DEBUG(my_logger, "some debug message {} {}", 3, 4); -/////////////////////////////////////////////////////////////////////////////// +// #ifdef SPDLOG_TRACE_ON #define SPDLOG_STR_H(x) #x @@ -165,5 +317,4 @@ inline void shutdown() #endif } // namespace spdlog - -#endif // #define SPDLOG_H +#endif // SPDLOG_H diff --git a/include/spdlog/version.h b/include/spdlog/version.h index b12cb7b3..16b9194b 100644 --- a/include/spdlog/version.h +++ b/include/spdlog/version.h @@ -6,7 +6,7 @@ #pragma once #define SPDLOG_VER_MAJOR 1 -#define SPDLOG_VER_MINOR 2 +#define SPDLOG_VER_MINOR 3 #define SPDLOG_VER_PATCH 0 #define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH) diff --git a/tests/includes.h b/tests/includes.h index 2090bcb4..3379f2c2 100644 --- a/tests/includes.h +++ b/tests/includes.h @@ -14,6 +14,7 @@ #define SPDLOG_DEBUG_ON #define SPDLOG_ENABLE_MESSAGE_COUNTER +#include "spdlog/spdlog.h" #include "spdlog/async.h" #include "spdlog/sinks/basic_file_sink.h" #include "spdlog/sinks/daily_file_sink.h" @@ -21,4 +22,3 @@ #include "spdlog/sinks/ostream_sink.h" #include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/sinks/stdout_color_sinks.h" -#include "spdlog/spdlog.h" diff --git a/tests/registry.cpp b/tests/registry.cpp index 1b841a4c..face26d3 100644 --- a/tests/registry.cpp +++ b/tests/registry.cpp @@ -12,8 +12,7 @@ TEST_CASE("register_drop", "[registry]") REQUIRE_THROWS_AS(spdlog::create(tested_logger_name), const spdlog::spdlog_ex &); } -TEST_CASE("explicit register" - "[registry]") +TEST_CASE("explicit register", "[registry]") { spdlog::drop_all(); auto logger = std::make_shared(tested_logger_name, std::make_shared()); @@ -23,8 +22,7 @@ TEST_CASE("explicit register" REQUIRE_THROWS_AS(spdlog::create(tested_logger_name), const spdlog::spdlog_ex &); } -TEST_CASE("apply_all" - "[registry]") +TEST_CASE("apply_all", "[registry]") { spdlog::drop_all(); auto logger = std::make_shared(tested_logger_name, std::make_shared()); @@ -45,8 +43,7 @@ TEST_CASE("apply_all" REQUIRE(counter == 1); } -TEST_CASE("drop" - "[registry]") +TEST_CASE("drop", "[registry]") { spdlog::drop_all(); spdlog::create(tested_logger_name); @@ -54,8 +51,7 @@ TEST_CASE("drop" REQUIRE_FALSE(spdlog::get(tested_logger_name)); } -TEST_CASE("drop_all" - "[registry]") +TEST_CASE("drop_all", "[registry]") { spdlog::drop_all(); spdlog::create(tested_logger_name); @@ -65,8 +61,7 @@ TEST_CASE("drop_all" REQUIRE_FALSE(spdlog::get(tested_logger_name2)); } -TEST_CASE("drop non existing" - "[registry]") +TEST_CASE("drop non existing", "[registry]") { spdlog::drop_all(); spdlog::create(tested_logger_name); @@ -75,3 +70,11 @@ TEST_CASE("drop non existing" REQUIRE(spdlog::get(tested_logger_name)); spdlog::drop_all(); } + +TEST_CASE("default logger", "[registry]") +{ + spdlog::drop_all(); + spdlog::set_default_logger(std::move(spdlog::null_logger_st(tested_logger_name))); + REQUIRE(spdlog::get(tested_logger_name) == spdlog::get()); + spdlog::drop_all(); +} diff --git a/tests/test_misc.cpp b/tests/test_misc.cpp index 66ae7c87..274a328e 100644 --- a/tests/test_misc.cpp +++ b/tests/test_misc.cpp @@ -191,3 +191,42 @@ TEST_CASE("message_counter", "[message_counter]") REQUIRE(oss.str() == "000002 Hello again" + std::string(spdlog::details::os::default_eol)); } + +TEST_CASE("default logger API", "[default logger]") +{ + std::ostringstream oss; + auto oss_sink = std::make_shared(oss); + + spdlog::set_default_logger(std::make_shared("oss", oss_sink)); + spdlog::get()->set_pattern("%v"); + + spdlog::get()->set_level(spdlog::level::trace); + spdlog::trace("hello trace"); + REQUIRE(oss.str() == "hello trace" + std::string(spdlog::details::os::default_eol)); + + oss.str(""); + spdlog::debug("hello debug"); + REQUIRE(oss.str() == "hello debug" + std::string(spdlog::details::os::default_eol)); + + oss.str(""); + spdlog::info("Hello"); + REQUIRE(oss.str() == "Hello" + std::string(spdlog::details::os::default_eol)); + + oss.str(""); + spdlog::warn("Hello again {}", 2); + REQUIRE(oss.str() == "Hello again 2" + std::string(spdlog::details::os::default_eol)); + + oss.str(""); + spdlog::error(123); + REQUIRE(oss.str() == "123" + std::string(spdlog::details::os::default_eol)); + + oss.str(""); + spdlog::critical(std::string("some string")); + REQUIRE(oss.str() == "some string" + std::string(spdlog::details::os::default_eol)); + + oss.str(""); + spdlog::set_level(spdlog::level::info); + spdlog::debug("should not be logged"); + REQUIRE(oss.str().empty()); + spdlog::drop_all(); +}