diff --git a/c11logtest/c11logtest/c11logtest.vcxproj b/c11logtest/c11logtest/c11logtest.vcxproj index dea51281..3c046302 100644 --- a/c11logtest/c11logtest/c11logtest.vcxproj +++ b/c11logtest/c11logtest/c11logtest.vcxproj @@ -91,10 +91,11 @@ + - + diff --git a/c11logtest/c11logtest/c11logtest.vcxproj.filters b/c11logtest/c11logtest/c11logtest.vcxproj.filters index 6373709b..4794c326 100644 --- a/c11logtest/c11logtest/c11logtest.vcxproj.filters +++ b/c11logtest/c11logtest/c11logtest.vcxproj.filters @@ -90,11 +90,14 @@ Header Files\c11log\sinks - + + Header Files\c11log\details + + Header Files\c11log\details - Header Files\c11log + Header Files\c11log\details diff --git a/example/bench.cpp b/example/bench.cpp index a0e24f6f..807cb2c3 100644 --- a/example/bench.cpp +++ b/example/bench.cpp @@ -1,6 +1,5 @@ // example.cpp : Simple logger example // -#include #include "c11log/logger.h" #include "c11log/sinks/async_sink.h" #include "c11log/sinks/file_sinks.h" @@ -18,16 +17,18 @@ int main(int argc, char* argv[]) { const unsigned int howmany = argc <= 1 ? 600000 : atoi(argv[1]); - auto console = c11log::create("reporter"); - console->set_format("[%n %l] %t"); + c11log::set_format("%t"); + auto console = c11log::create("reporter"); + //console->set_format("[%n %l] %t"); console->set_level(c11log::level::INFO); console->info("Starting bench with", howmany, "iterations.."); - auto bench = c11log::create("bench", "myrotating", "txt", 1024 * 1024 * 5, 3, 100); + //auto bench = c11log::create("bench", "myrotating", "txt", 1024 * 1024 * 5, 3, 100); + auto bench = c11log::create("bench"); auto start = system_clock::now(); for (unsigned int i = 1; i <= howmany; ++i) { - bench->info() << "Hello logger: msg number " << i; + c11log::get("bench")->info("Hello logger: msg number", i); } auto delta = system_clock::now() - start; diff --git a/include/c11log/details/logger_impl.h b/include/c11log/details/logger_impl.h new file mode 100644 index 00000000..aca750a8 --- /dev/null +++ b/include/c11log/details/logger_impl.h @@ -0,0 +1,168 @@ +#pragma once +// +// Logger implementation +// + + +#include "details/line_logger.h" + + +inline c11log::logger::logger(const std::string& logger_name, sinks_init_list sinks_list) : + _name(logger_name), + _sinks(sinks_list) +{ + // no support under vs2013 for member initialization for std::atomic + _level = level::INFO; +} + +template +inline c11log::logger::logger(const std::string& logger_name, const It& begin, const It& end) : + _name(logger_name), + _sinks(begin, end) +{} + + +inline void c11log::logger::set_formatter(c11log::formatter_ptr msg_formatter) +{ + _formatter = msg_formatter; +} + +inline void c11log::logger::set_format(const std::string& format) +{ + _formatter = std::make_shared(format); +} + +inline c11log::formatter_ptr c11log::logger::get_formatter() const +{ + return _formatter; +} + + +template +inline c11log::details::line_logger c11log::logger::log(level::level_enum lvl, const Args&... args) { + bool msg_enabled = should_log(lvl); + details::line_logger l(this, lvl, msg_enabled); + if (msg_enabled) + _variadic_log(l, args...); + return l; +} + +template +inline c11log::details::line_logger c11log::logger::trace(const Args&... args) +{ + return log(level::TRACE, args...); +} + +template +inline c11log::details::line_logger c11log::logger::debug(const Args&... args) +{ + return log(level::DEBUG, args...); +} + +template +inline c11log::details::line_logger c11log::logger::info(const Args&... args) +{ + return log(level::INFO, args...); +} + +template +inline c11log::details::line_logger c11log::logger::warn(const Args&... args) +{ + return log(level::WARN, args...); +} + +template +inline c11log::details::line_logger c11log::logger::error(const Args&... args) +{ + return log(level::ERR, args...); +} + +template +inline c11log::details::line_logger c11log::logger::critical(const Args&... args) +{ + return log(level::CRITICAL, args...); +} + +inline const std::string& c11log::logger::name() const +{ + return _name; +} + +inline void c11log::logger::set_level(c11log::level::level_enum log_level) +{ + _level.store(log_level); +} + +inline c11log::level::level_enum c11log::logger::level() const +{ + return static_cast(_level.load()); +} + +inline bool c11log::logger::should_log(c11log::level::level_enum msg_level) const +{ + return msg_level >= _level.load(); +} + +inline void c11log::logger::_variadic_log(c11log::details::line_logger&) {} + +template +void c11log::logger::_variadic_log(c11log::details::line_logger& l, const First& first, const Rest&... rest) +{ + l.write(first); + l.write(' '); + _variadic_log(l, rest...); +} + +inline void c11log::logger::_log_msg(details::log_msg& msg) +{ + if (!_formatter) + _formatter = std::make_shared("%+ %t"); + _formatter->format(msg); + for (auto &sink : _sinks) + sink->log(msg); +} + +// +// Global registry functions +// +#include "details/registry.h" +inline std::shared_ptr c11log::get(const std::string& name) +{ + return details::registry::instance().get(name); +} + +inline std::shared_ptr c11log::create(const std::string& logger_name, c11log::sinks_init_list sinks) +{ + return details::registry::instance().create(logger_name, sinks); +} + + +template +inline std::shared_ptr c11log::create(const std::string& logger_name, const Args&... args) +{ + sink_ptr sink = std::make_shared(args...); + return details::registry::instance().create(logger_name, { sink }); +} + + +template +inline std::shared_ptr c11log::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) +{ + return details::registry::instance().create(logger_name, std::forward(sinks_begin), std::forward(sinks_end)); +} + + +inline void c11log::formatter(c11log::formatter_ptr f) +{ + return details::registry::instance().formatter(f); +} + +inline c11log::formatter_ptr c11log::formatter() +{ + return details::registry::instance().formatter(); +} + +inline void c11log::set_format(const std::string& format_string) +{ + return details::registry::instance().set_format(format_string); +} diff --git a/include/c11log/details/pattern_formatter.h b/include/c11log/details/pattern_formatter_impl.h similarity index 93% rename from include/c11log/details/pattern_formatter.h rename to include/c11log/details/pattern_formatter_impl.h index 98d07b75..cdcf9401 100644 --- a/include/c11log/details/pattern_formatter.h +++ b/include/c11log/details/pattern_formatter_impl.h @@ -22,6 +22,7 @@ public: /////////////////////////////////////////////////////////////////////// // name & level pattern appenders /////////////////////////////////////////////////////////////////////// +namespace { class name_formatter :public flag_formatter { void format(details::log_msg& msg) override @@ -29,6 +30,7 @@ class name_formatter :public flag_formatter msg.formatted << msg.logger_name; } }; +} // log level appender class level_formatter :public flag_formatter @@ -374,35 +376,20 @@ class full_formatter :public flag_formatter } }; - - -class pattern_formatter : public formatter -{ - -public: - explicit pattern_formatter(const std::string& pattern); - pattern_formatter(const pattern_formatter&) = delete; - void format(details::log_msg& msg) override; -private: - const std::string _pattern; - std::vector> _formatters; - void handle_flag(char flag); - void compile_pattern(const std::string& pattern); -}; } } /////////////////////////////////////////////////////////////////////////////// // pattern_formatter inline impl /////////////////////////////////////////////////////////////////////////////// -inline c11log::details::pattern_formatter::pattern_formatter(const std::string& pattern) +inline c11log::pattern_formatter::pattern_formatter(const std::string& pattern) { compile_pattern(pattern); } -inline void c11log::details::pattern_formatter::compile_pattern(const std::string& pattern) +inline void c11log::pattern_formatter::compile_pattern(const std::string& pattern) { auto end = pattern.end(); - std::unique_ptr user_chars; + std::unique_ptr user_chars; for (auto it = pattern.begin(); it != end; ++it) { if (*it == '%') @@ -418,7 +405,7 @@ inline void c11log::details::pattern_formatter::compile_pattern(const std::strin else // chars not following the % sign should be displayed as is { if (!user_chars) - user_chars = std::unique_ptr(new aggregate_formatter()); + user_chars = std::unique_ptr(new details::aggregate_formatter()); user_chars->add_ch(*it); } } @@ -428,7 +415,7 @@ inline void c11log::details::pattern_formatter::compile_pattern(const std::strin } } -inline void c11log::details::pattern_formatter::handle_flag(char flag) +inline void c11log::pattern_formatter::handle_flag(char flag) { switch (flag) { @@ -540,7 +527,7 @@ inline void c11log::details::pattern_formatter::handle_flag(char flag) } -inline void c11log::details::pattern_formatter::format(details::log_msg& msg) +inline void c11log::pattern_formatter::format(details::log_msg& msg) { for (auto &f : _formatters) { diff --git a/include/c11log/details/registry.h b/include/c11log/details/registry.h index 9b0ae81b..71c0738c 100644 --- a/include/c11log/details/registry.h +++ b/include/c11log/details/registry.h @@ -1,6 +1,6 @@ #pragma once // Loggers registy of unique name->logger pointer -// If 2 loggers with same name are added, the last will be used +// If 2 loggers with same name are added, the second will be overrun the first // If user requests a non existing logger, nullptr will be returned // This class is thread safe @@ -23,12 +23,15 @@ public: std::shared_ptr create(const std::string& logger_name, sinks_init_list sinks) { std::lock_guard l(_mutex); - return _loggers[logger_name] = std::make_shared(logger_name, sinks); + auto new_logger = std::make_shared(logger_name, sinks); + new_logger->set_formatter(_formatter); + _loggers[logger_name] = new_logger; + return new_logger; } std::shared_ptr create(const std::string& logger_name, sink_ptr sink) { - create(logger_name, { sink }); + return create(logger_name, { sink }); } @@ -36,10 +39,27 @@ public: std::shared_ptr create (const std::string& logger_name, const It& sinks_begin, const It& sinks_end) { std::lock_guard l(_mutex); - return _loggers[logger_name] = std::make_shared(logger_name, sinks_begin, sinks_end); + auto new_logger = std::make_shared(logger_name, sinks_begin, sinks_end); + new_logger->set_formatter(_formatter); + _loggers[logger_name] = new_logger; + return new_logger; + } + void formatter(formatter_ptr f) + { + _formatter = f; + } + formatter_ptr formatter() + { + return _formatter; + } + + void set_format(const std::string& format_string) + { + _formatter = std::make_shared(format_string); + } static registry& instance() @@ -53,6 +73,7 @@ private: registry(const registry&) = delete; std::mutex _mutex; std::unordered_map > _loggers; + formatter_ptr _formatter; }; } diff --git a/include/c11log/formatter.h b/include/c11log/formatter.h index 9651729f..12c4dfca 100644 --- a/include/c11log/formatter.h +++ b/include/c11log/formatter.h @@ -1,7 +1,11 @@ #pragma once + #include "details/log_msg.h" namespace c11log { +namespace details { +class flag_formatter; +} class formatter { @@ -9,4 +13,21 @@ public: virtual ~formatter() {} virtual void format(details::log_msg& msg) = 0; }; + +class pattern_formatter : public formatter +{ + +public: + explicit pattern_formatter(const std::string& pattern); + pattern_formatter(const pattern_formatter&) = delete; + void format(details::log_msg& msg) override; +private: + const std::string _pattern; + std::vector> _formatters; + void handle_flag(char flag); + void compile_pattern(const std::string& pattern); +}; } + +#include "./details/pattern_formatter_impl.h" + diff --git a/include/c11log/logger.h b/include/c11log/logger.h index d405697e..c43c3782 100644 --- a/include/c11log/logger.h +++ b/include/c11log/logger.h @@ -11,11 +11,9 @@ #include #include #include - +#include #include "sinks/base_sink.h" #include "common.h" -#include "details/pattern_formatter.h" - namespace c11log { @@ -55,10 +53,6 @@ public: template details::line_logger error(const Args&... args); template details::line_logger critical(const Args&... args); - //static functions - //get/set default formatter - static formatter_ptr default_formatter(formatter_ptr formatter = nullptr); - static formatter_ptr default_format(const std::string& format); private: friend details::line_logger; @@ -72,6 +66,18 @@ private: void _log_msg(details::log_msg& msg); }; +class fflog_exception : public std::exception +{ +public: + fflog_exception(const std::string& msg) :_msg(msg) {}; + const char* what() const throw() override { + return _msg.c_str(); + } +private: + std::string _msg; + +}; + // // Registry functions for easy loggers creation and retrieval // example @@ -80,14 +86,15 @@ private: // auto file_logger = c11 // std::shared_ptr get(const std::string& name); - std::shared_ptr create(const std::string& logger_name, sinks_init_list sinks); - template std::shared_ptr create(const std::string& logger_name, const Args&... args); - template std::shared_ptr create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end); + +void formatter(formatter_ptr f); +formatter_ptr formatter(); +void set_format(const std::string& format_string); } // @@ -105,173 +112,4 @@ std::shared_ptr create(const std::string& logger_name, const It& sinks_b #define FFLOG_DEBUG(logger, ...) {} #endif -// -// Logger implementation -// - -#include "details/line_logger.h" - - -inline c11log::logger::logger(const std::string& logger_name, sinks_init_list sinks_list): - _name(logger_name), - _sinks(sinks_list) -{ - // no support under vs2013 for member initialization for std::atomic - _level = level::INFO; -} - -template -inline c11log::logger::logger(const std::string& logger_name, const It& begin, const It& end) : - _name(logger_name), - _sinks(begin, end) -{} - - -inline void c11log::logger::set_formatter(c11log::formatter_ptr msg_formatter) -{ - _formatter = msg_formatter; -} - -inline void c11log::logger::set_format(const std::string& format) -{ - _formatter = std::make_shared(format); -} - -inline c11log::formatter_ptr c11log::logger::get_formatter() const -{ - return _formatter; -} - -inline c11log::formatter_ptr c11log::logger::default_formatter(formatter_ptr formatter) -{ - static formatter_ptr g_default_formatter = std::make_shared("[%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %t"); - if (formatter) - g_default_formatter = formatter; - return g_default_formatter; -} - -inline c11log::formatter_ptr c11log::logger::default_format(const std::string& format) -{ - return default_formatter(std::make_shared(format)); -} - -template -inline c11log::details::line_logger c11log::logger::log(level::level_enum lvl, const Args&... args) { - bool msg_enabled = should_log(lvl); - details::line_logger l(this, lvl, msg_enabled); - if (msg_enabled) - _variadic_log(l, args...); - return l; -} - -template -inline c11log::details::line_logger c11log::logger::trace(const Args&... args) -{ - return log(level::TRACE, args...); -} - -template -inline c11log::details::line_logger c11log::logger::debug(const Args&... args) -{ - return log(level::DEBUG, args...); -} - -template -inline c11log::details::line_logger c11log::logger::info(const Args&... args) -{ - return log(level::INFO, args...); -} - -template -inline c11log::details::line_logger c11log::logger::warn(const Args&... args) -{ - return log(level::WARN, args...); -} - -template -inline c11log::details::line_logger c11log::logger::error(const Args&... args) -{ - return log(level::ERR, args...); -} - -template -inline c11log::details::line_logger c11log::logger::critical(const Args&... args) -{ - return log(level::CRITICAL, args...); -} - -inline const std::string& c11log::logger::name() const -{ - return _name; -} - -inline void c11log::logger::set_level(c11log::level::level_enum log_level) -{ - _level.store(log_level); -} - -inline c11log::level::level_enum c11log::logger::level() const -{ - return static_cast(_level.load()); -} - -inline bool c11log::logger::should_log(c11log::level::level_enum msg_level) const -{ - return msg_level >= _level.load(); -} - - - - -inline void c11log::logger::_variadic_log(c11log::details::line_logger&) {} - -template -void c11log::logger::_variadic_log(c11log::details::line_logger& l, const First& first, const Rest&... rest) -{ - l.write(first); - l.write(' '); - _variadic_log(l, rest...); -} - -inline void c11log::logger::_log_msg(details::log_msg& msg) -{ - if(!_formatter) - _formatter = logger::default_formatter(); - _formatter->format(msg); - for (auto &sink : _sinks) - sink->log(msg); -} - -// -// Global registry functions -// -#include "details/registry.h" -inline std::shared_ptr c11log::get(const std::string& name) -{ - return details::registry::instance().get(name); -} - -inline std::shared_ptr c11log::create(const std::string& logger_name, c11log::sinks_init_list sinks) -{ - return details::registry::instance().create(logger_name, sinks); -} - - -template -inline std::shared_ptr c11log::create(const std::string& logger_name, const Args&... args) -{ - sink_ptr sink = std::make_shared(args...); - return details::registry::instance().create(logger_name, { sink }); -} - - - -template -inline std::shared_ptr c11log::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) -{ - std::lock_guard l(_mutex); - return details::registry::instance().create(logger_name, std::forward(sinks_begin), std::forward(sinks_end)); -} - - - +#include "./details/logger_impl.h" \ No newline at end of file