Commit 0cfdad4d authored by gabime's avatar gabime

Windows console color support. Replaced color param in API with new functions

parent 94dbefe9
...@@ -70,81 +70,87 @@ void user_defined_example(); ...@@ -70,81 +70,87 @@ void user_defined_example();
void err_handler_example(); void err_handler_example();
namespace spd = spdlog; namespace spd = spdlog;
int main(int, char*[]) int main(int, char*[])
{ {
try try
{ {
// Multithreaded color console // Console logger with color
auto console = spd::stdout_logger_mt("console", true); auto console = spd::stdout_color_mt("console");
console->info("Welcome to spdlog!"); console->info("Welcome to spdlog!");
console->info("An info message example {}..", 1); console->error("Some error message with arg{}..", 1);
// Formatting examples // Formatting examples
console->warn("Easy padding in numbers like {:08d}", 12); 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->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("Support for floats {:03.2f}", 1.23456);
console->info("Positional args are {1} {0}..", "too", "supported"); console->info("Positional args are {1} {0}..", "too", "supported");
console->info("{:<30}", "left aligned");
console->info("{:<30}", "left aligned");
console->info("{:>30}", "right aligned");
console->info("{:^30}", "centered"); spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function"); // Create basic file logger (not rotated)
auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic.txt");
// Runtime log levels my_logger->info("Some log message");
spd::set_level(spd::level::info); //Set global log level to info
console->debug("This message shold not be displayed!"); // Create a file rotating logger with 5mb size max and 3 rotated files
console->set_level(spd::level::debug); // Set specific logger's log level auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/mylogfile", 1048576 * 5, 3);
console->debug("This message shold be displayed.."); for (int i = 0; i < 10; ++i)
rotating_logger->info("{} * {} equals {:>10}", i, i, i*i);
// Create basic file logger (not rotated)
auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic.txt"); // Create a daily logger - a new file is created every day on 2:30am
my_logger->info("Some log message"); auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily", 2, 30);
// trigger flush if the log severity is error or higher
daily_logger->flush_on(spd::level::err);
// Create a file rotating logger with 5mb size max and 3 rotated files daily_logger->info(123.44);
auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/mylogfile", 1048576 * 5, 3);
for (int i = 0; i < 10; ++i) // Customize msg format for all messages
rotating_logger->info("{} * {} equals {:>10}", i, i, i*i); spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
rotating_logger->info("This is another message with custom format");
// Create a daily logger - a new file is created every day on 2:30am
auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily", 2, 30);
daily_logger->info(123.44); // Runtime log levels
spd::set_level(spd::level::info); //Set global log level to info
// Customize msg format for all messages console->debug("This message shold not be displayed!");
spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***"); console->set_level(spd::level::debug); // Set specific logger's log level
rotating_logger->info("This is another message with custom format"); console->debug("This message shold be displayed..");
// Compile time debug or trace macros. // Compile time log levels
// Enabled #ifdef SPDLOG_DEBUG_ON or #ifdef SPDLOG_TRACE_ON // define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON
SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23); SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23); SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
// Asynchronous logging is very fast.. // Asynchronous logging is very fast..
// Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous.. // Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
async_example(); async_example();
// syslog example. linux/osx only.. // syslog example. linux/osx only
syslog_example(); syslog_example();
// Log user-defined types example.. // android example. compile with NDK
user_defined_example(); android_example();
// Change default log error handler // Log user-defined types example
err_handler_example(); user_defined_example();
// Apply a function on all registered loggers // Change default log error handler
spd::apply_all([&](std::shared_ptr<spdlog::logger> l) {l->info("End of example."); }); err_handler_example();
// Release and close all loggers // Apply a function on all registered loggers
spdlog::drop_all(); spd::apply_all([&](std::shared_ptr<spdlog::logger> l)
} {
// Exceptions will only be thrown upon failed logger or sink construction (not during logging) l->info("End of example.");
catch (const spd::spdlog_ex& ex) });
{
std::cout << "Log init failed: " << ex.what() << std::endl; // Release and close all loggers
return 1; spdlog::drop_all();
} }
// Exceptions will only be thrown upon failed logger or sink construction (not during logging)
catch (const spd::spdlog_ex& ex)
{
std::cout << "Log init failed: " << ex.what() << std::endl;
return 1;
}
} }
void async_example() void async_example()
......
...@@ -22,29 +22,22 @@ int main(int, char*[]) ...@@ -22,29 +22,22 @@ int main(int, char*[])
{ {
try try
{ {
// Multithreaded color console // Console logger with color
auto console = spd::stdout_logger_mt("console", true); auto console = spd::stdout_color_mt("console");
console->info("Welcome to spdlog!"); console->info("Welcome to spdlog!");
console->error("An error message example {}..", 1); console->error("Some error message with arg{}..", 1);
// Formatting examples // Formatting examples
console->warn("Easy padding in numbers like {:08d}", 12); 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->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("Support for floats {:03.2f}", 1.23456);
console->info("Positional args are {1} {0}..", "too", "supported"); console->info("Positional args are {1} {0}..", "too", "supported");
console->info("{:<30}", "left aligned"); console->info("{:<30}", "left aligned");
console->info("{:>30}", "right aligned");
console->info("{:^30}", "centered");
spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function"); spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
// Runtime log levels
spd::set_level(spd::level::info); //Set global log level to info
console->debug("This message shold not be displayed!");
console->set_level(spd::level::debug); // Set specific logger's log level
console->debug("This message shold be displayed..");
// Create basic file logger (not rotated) // Create basic file logger (not rotated)
auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic.txt"); auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic.txt");
my_logger->info("Some log message"); my_logger->info("Some log message");
...@@ -64,8 +57,15 @@ int main(int, char*[]) ...@@ -64,8 +57,15 @@ int main(int, char*[])
spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***"); spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
rotating_logger->info("This is another message with custom format"); rotating_logger->info("This is another message with custom format");
// Compile time debug or trace macros.
// Enabled #ifdef SPDLOG_DEBUG_ON or #ifdef SPDLOG_TRACE_ON // Runtime log levels
spd::set_level(spd::level::info); //Set global log level to info
console->debug("This message shold not be displayed!");
console->set_level(spd::level::debug); // Set specific logger's log level
console->debug("This message shold be displayed..");
// 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_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23); SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
<ClInclude Include="..\include\spdlog\sinks\sink.h" /> <ClInclude Include="..\include\spdlog\sinks\sink.h" />
<ClInclude Include="..\include\spdlog\sinks\stdout_sinks.h" /> <ClInclude Include="..\include\spdlog\sinks\stdout_sinks.h" />
<ClInclude Include="..\include\spdlog\sinks\syslog_sink.h" /> <ClInclude Include="..\include\spdlog\sinks\syslog_sink.h" />
<ClInclude Include="..\include\spdlog\sinks\wincolor_sink.h" />
<ClInclude Include="..\include\spdlog\spdlog.h" /> <ClInclude Include="..\include\spdlog\spdlog.h" />
<ClInclude Include="..\include\spdlog\tweakme.h" /> <ClInclude Include="..\include\spdlog\tweakme.h" />
</ItemGroup> </ItemGroup>
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
#ifdef SPDLOG_ENABLE_SYSLOG #ifdef SPDLOG_ENABLE_SYSLOG
#include <spdlog/sinks/syslog_sink.h> #include <spdlog/sinks/syslog_sink.h>
#endif #endif
#ifdef _WIN32
#include <spdlog/sinks/wincolor_sink.h>
#else
#include <spdlog/sinks/ansicolor_sink.h> #include <spdlog/sinks/ansicolor_sink.h>
#endif
#ifdef __ANDROID__ #ifdef __ANDROID__
#include <spdlog/sinks/android_sink.h> #include <spdlog/sinks/android_sink.h>
...@@ -28,160 +34,212 @@ ...@@ -28,160 +34,212 @@
inline void spdlog::register_logger(std::shared_ptr<logger> logger) inline void spdlog::register_logger(std::shared_ptr<logger> logger)
{ {
return details::registry::instance().register_logger(logger); return details::registry::instance().register_logger(logger);
} }
inline std::shared_ptr<spdlog::logger> spdlog::get(const std::string& name) inline std::shared_ptr<spdlog::logger> spdlog::get(const std::string& name)
{ {
return details::registry::instance().get(name); return details::registry::instance().get(name);
} }
inline void spdlog::drop(const std::string &name) inline void spdlog::drop(const std::string &name)
{ {
details::registry::instance().drop(name); details::registry::instance().drop(name);
} }
// Create multi/single threaded simple file logger // Create multi/single threaded simple file logger
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate) inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate)
{ {
return create<spdlog::sinks::simple_file_sink_mt>(logger_name, filename, truncate); return create<spdlog::sinks::simple_file_sink_mt>(logger_name, filename, truncate);
} }
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate) inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate)
{ {
return create<spdlog::sinks::simple_file_sink_st>(logger_name, filename, truncate); return create<spdlog::sinks::simple_file_sink_st>(logger_name, filename, truncate);
} }
// Create multi/single threaded rotating file logger // Create multi/single threaded rotating file logger
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files) inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
{ {
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files); return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files);
} }
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files) inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
{ {
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files); return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files);
} }
// Create file logger which creates new file at midnight): // Create file logger which creates new file at midnight):
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute) inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute)
{ {
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute); return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute);
} }
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute) inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute)
{ {
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute); return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute);
}
//
// stdout/stderr loggers
//
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name)
{
return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance());
}
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name)
{
return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance());
} }
// Create stdout/stderr loggers (with optinal color support) inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name)
inline std::shared_ptr<spdlog::logger> create_console_logger(const std::string& logger_name, spdlog::sink_ptr sink, bool color)
{ {
if (color) //use color wrapper sink return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance());
sink = std::make_shared<spdlog::sinks::ansicolor_sink>(sink);
return spdlog::details::registry::instance().create(logger_name, sink);
} }
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name, bool color) inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name)
{ {
return create_console_logger(logger_name, sinks::stdout_sink_mt::instance(), color); return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance());
} }
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name, bool color) //
// stdout/stderr color loggers
//
#ifdef _WIN32
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string& logger_name)
{ {
return create_console_logger(logger_name, sinks::stdout_sink_st::instance(), color); auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();
return spdlog::details::registry::instance().create(logger_name, sink);
} }
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name, bool color) inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string& logger_name)
{ {
return create_console_logger(logger_name, sinks::stderr_sink_mt::instance(), color); auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_st>();
return spdlog::details::registry::instance().create(logger_name, sink);
} }
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name, bool color) inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string& logger_name)
{ {
return create_console_logger(logger_name, sinks::stderr_sink_st::instance(), color); auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_mt>();
return spdlog::details::registry::instance().create(logger_name, sink);
} }
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string& logger_name)
{
auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_st>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
#else //ansi terminal colors
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string& logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_sink>(spdlog::sinks::stdout_sink_mt::instance());
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string& logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_sink>(spdlog::sinks::stdout_sink_st::instance());
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string& logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_sink>(spdlog::sinks::stderr_sink_mt::instance());
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string& logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_sink>(spdlog::sinks::stderr_sink_st::instance());
return spdlog::details::registry::instance().create(logger_name, sink);
}
#endif
#ifdef SPDLOG_ENABLE_SYSLOG #ifdef SPDLOG_ENABLE_SYSLOG
// Create syslog logger // Create syslog logger
inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option) inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option)
{ {
return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option); return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option);
} }
#endif #endif
#ifdef __ANDROID__ #ifdef __ANDROID__
inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string& logger_name, const std::string& tag) inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string& logger_name, const std::string& tag)
{ {
return create<spdlog::sinks::android_sink>(logger_name, tag); return create<spdlog::sinks::android_sink>(logger_name, tag);
} }
#endif #endif
// Create and register a logger a single sink // Create and register a logger a single sink
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const spdlog::sink_ptr& sink) inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const spdlog::sink_ptr& sink)
{ {
return details::registry::instance().create(logger_name, sink); return details::registry::instance().create(logger_name, sink);
} }
//Create logger with multiple sinks //Create logger with multiple sinks
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks) inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks)
{ {
return details::registry::instance().create(logger_name, sinks); return details::registry::instance().create(logger_name, sinks);
} }
template <typename Sink, typename... Args> template <typename Sink, typename... Args>
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, Args... args) inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, Args... args)
{ {
sink_ptr sink = std::make_shared<Sink>(args...); sink_ptr sink = std::make_shared<Sink>(args...);
return details::registry::instance().create(logger_name, { sink }); return details::registry::instance().create(logger_name, { sink });
} }
template<class It> template<class It>
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
{ {
return details::registry::instance().create(logger_name, sinks_begin, sinks_end); return details::registry::instance().create(logger_name, sinks_begin, sinks_end);
} }
inline void spdlog::set_formatter(spdlog::formatter_ptr f) inline void spdlog::set_formatter(spdlog::formatter_ptr f)
{ {
details::registry::instance().formatter(f); details::registry::instance().formatter(f);
} }
inline void spdlog::set_pattern(const std::string& format_string) inline void spdlog::set_pattern(const std::string& format_string)
{ {
return details::registry::instance().set_pattern(format_string); return details::registry::instance().set_pattern(format_string);
} }
inline void spdlog::set_level(level::level_enum log_level) inline void spdlog::set_level(level::level_enum log_level)
{ {
return details::registry::instance().set_level(log_level); return details::registry::instance().set_level(log_level);
} }
inline void spdlog::set_error_handler(log_err_handler handler) inline void spdlog::set_error_handler(log_err_handler handler)
{ {
return details::registry::instance().set_error_handler(handler); return details::registry::instance().set_error_handler(handler);
} }
inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb) inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
{ {
details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb); details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
} }
inline void spdlog::set_sync_mode() inline void spdlog::set_sync_mode()
{ {
details::registry::instance().set_sync_mode(); details::registry::instance().set_sync_mode();
} }
inline void spdlog::apply_all(std::function<void(std::shared_ptr<logger>)> fun) inline void spdlog::apply_all(std::function<void(std::shared_ptr<logger>)> fun)
{ {
details::registry::instance().apply_all(fun); details::registry::instance().apply_all(fun);
} }
inline void spdlog::drop_all() inline void spdlog::drop_all()
{ {
details::registry::instance().drop_all(); details::registry::instance().drop_all();
} }
...@@ -14,62 +14,64 @@ ...@@ -14,62 +14,64 @@
namespace spdlog namespace spdlog
{ {
namespace sinks namespace sinks
{ {
template <class Mutex> template <class Mutex>
class stdout_sink : public base_sink<Mutex> class stdout_sink: public base_sink<Mutex>
{ {
using MyType = stdout_sink<Mutex>; using MyType = stdout_sink<Mutex>;
public: public:
stdout_sink() {} stdout_sink()
static std::shared_ptr<MyType> instance() {}
{ static std::shared_ptr<MyType> instance()
static std::shared_ptr<MyType> instance = std::make_shared<MyType>(); {
return instance; static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
} return instance;
}
void _sink_it(const details::log_msg& msg) override void _sink_it(const details::log_msg& msg) override
{ {
fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout); fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout);
flush(); flush();
} }
void flush() override void flush() override
{ {
fflush(stdout); fflush(stdout);
} }
}; };
typedef stdout_sink<details::null_mutex> stdout_sink_st; typedef stdout_sink<details::null_mutex> stdout_sink_st;
typedef stdout_sink<std::mutex> stdout_sink_mt; typedef stdout_sink<std::mutex> stdout_sink_mt;
template <class Mutex> template <class Mutex>
class stderr_sink : public base_sink<Mutex> class stderr_sink: public base_sink<Mutex>
{ {
using MyType = stderr_sink<Mutex>; using MyType = stderr_sink<Mutex>;
public: public:
stderr_sink() {} stderr_sink()
static std::shared_ptr<MyType> instance() {}
{ static std::shared_ptr<MyType> instance()
static std::shared_ptr<MyType> instance = std::make_shared<MyType>(); {
return instance; static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
} return instance;
}
void _sink_it(const details::log_msg& msg) override void _sink_it(const details::log_msg& msg) override
{ {
fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stderr); fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stderr);
flush(); flush();
} }
void flush() override void flush() override
{ {
fflush(stderr); fflush(stderr);
} }
}; };
typedef stderr_sink<std::mutex> stderr_sink_mt; typedef stderr_sink<std::mutex> stderr_sink_mt;
typedef stderr_sink<details::null_mutex> stderr_sink_st; typedef stderr_sink<details::null_mutex> stderr_sink_st;
} }
} }
//
// Copyright(c) 2016 spdlog
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/common.h>
#include <mutex>
#include <string>
#include <map>
#include <wincon.h>
namespace spdlog
{
namespace sinks
{
/*
* Windows color console sink. Uses WriteConsoleA to write to the console with colors
*/
template<class Mutex>
class wincolor_sink: public base_sink<Mutex>
{
public:
const WORD BOLD = FOREGROUND_INTENSITY;
const WORD RED = FOREGROUND_RED;
const WORD CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE;
const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN;
wincolor_sink(HANDLE std_handle): out_handle_(std_handle)
{
colors_[level::trace] = CYAN;
colors_[level::debug] = CYAN;
colors_[level::info] = WHITE | BOLD;
colors_[level::warn] = YELLOW | BOLD;
colors_[level::err] = RED | BOLD; // red bold
colors_[level::critical] = BACKGROUND_RED | WHITE | BOLD; // white bold on red background
colors_[level::off] = 0;
}
virtual ~wincolor_sink()
{
flush();
}
wincolor_sink(const wincolor_sink& other) = delete;
wincolor_sink& operator=(const wincolor_sink& other) = delete;
virtual void _sink_it(const details::log_msg& msg) override
{
auto color = colors_[msg.level];
auto orig_attribs = set_console_attribs(color);
WriteConsoleA(out_handle_, msg.formatted.data(), msg.formatted.size(), nullptr, nullptr);
SetConsoleTextAttribute(out_handle_, orig_attribs); //reset to orig colors
}
virtual void flush() override
{
// windows console always flushed?
}
// change the color for the given level
void set_color(level::level_enum level, WORD color)
{
std::lock_guard<Mutex> lock(_mutex);
colors_[level] = color;
}
private:
HANDLE out_handle_;
std::map<level::level_enum, WORD> colors_;
// set color and return the orig console attributes (for resetting later)
WORD set_console_attribs(WORD attribs)
{
CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info;
GetConsoleScreenBufferInfo(out_handle_, &orig_buffer_info);
SetConsoleTextAttribute(out_handle_, attribs);
return orig_buffer_info.wAttributes; //return orig attribs
}
};
//
// windows color console to stdout
//
template<class Mutex>
class wincolor_stdout_sink: public wincolor_sink<Mutex>
{
public:
wincolor_stdout_sink():wincolor_sink(GetStdHandle(STD_OUTPUT_HANDLE))
{}
};
typedef wincolor_stdout_sink<std::mutex> wincolor_stdout_sink_mt;
typedef wincolor_stdout_sink<details::null_mutex> wincolor_stdout_sink_st;
//
// windows color console to stderr
//
template<class Mutex>
class wincolor_stderr_sink: public wincolor_sink<Mutex>
{
public:
wincolor_stderr_sink():wincolor_sink(GetStdHandle(STD_ERROR_HANDLE))
{}
};
typedef wincolor_stderr_sink<std::mutex> wincolor_stderr_sink_mt;
typedef wincolor_stderr_sink<details::null_mutex> wincolor_stderr_sink_st;
}
}
\ No newline at end of file
...@@ -88,10 +88,17 @@ std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const fi ...@@ -88,10 +88,17 @@ std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const fi
// //
// Create and register stdout/stderr loggers // Create and register stdout/stderr loggers
// //
std::shared_ptr<logger> stdout_logger_mt(const std::string& logger_name, bool color = false); std::shared_ptr<logger> stdout_logger_mt(const std::string& logger_name);
std::shared_ptr<logger> stdout_logger_st(const std::string& logger_name, bool color = false); std::shared_ptr<logger> stdout_logger_st(const std::string& logger_name);
std::shared_ptr<logger> stderr_logger_mt(const std::string& logger_name, bool color = false); std::shared_ptr<logger> stderr_logger_mt(const std::string& logger_name);
std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name, bool color = false); std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name);
//
// Create and register colored stdout/stderr loggers
//
std::shared_ptr<logger> stdout_color_mt(const std::string& logger_name);
std::shared_ptr<logger> stdout_color_st(const std::string& logger_name);
std::shared_ptr<logger> stderr_color_mt(const std::string& logger_name);
std::shared_ptr<logger> stderr_color_st(const std::string& logger_name);
// //
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment