diff --git a/example/example.cpp b/example/example.cpp index 07885927..c06d5a6d 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -2,7 +2,7 @@ // #include "c11log/logger.h" -#include "c11log/sinks/async_sink.h" +//#include "c11log/sinks/async_sink.h" #include "c11log/sinks/file_sinks.h" #include "c11log/sinks/console_sinks.h" @@ -19,7 +19,7 @@ int main(int argc, char* argv[]) { if(argc || argv) {}; - const unsigned int howmany = 1000000; + const unsigned int howmany = 5000000; auto fsink = std::make_shared("log", "txt", 1024*1024*50 , 5, 0); //auto fsink = std::make_shared("simplelog", "txt"); @@ -40,10 +40,10 @@ int main(int argc, char* argv[]) //async->shutdown(seconds(3)); auto delta = system_clock::now() - start; - auto delta_d = duration_cast> (delta); - cout << "Total " << format(howmany) << endl; - cout << "Delta " << format(delta_d.count()) << endl; - cout << "Rate: " << format(howmany/delta_d.count()) << "/sec" << endl; + auto delta_d = duration_cast> (delta).count(); + cout_logger.info() << "Total " << format(howmany); + cout_logger.info() << "Delta " << format(delta_d); + cout_logger.info() << "Rate: " << format(howmany/delta_d) << "/sec"; return 0; diff --git a/include/c11log/common_types.h b/include/c11log/common_types.h index b6dfba4b..9159ccec 100644 --- a/include/c11log/common_types.h +++ b/include/c11log/common_types.h @@ -26,4 +26,13 @@ inline const char* to_str(c11log::level::level_enum l) return level_names[l]; } } + +struct log_msg +{ + log_clock::time_point when; + bufpair_t msg_buf; + std::size_t header_size; + level::level_enum msg_level; +}; + } diff --git a/include/c11log/details/line_logger.h b/include/c11log/details/line_logger.h index e5f3c0bf..fae0131a 100644 --- a/include/c11log/details/line_logger.h +++ b/include/c11log/details/line_logger.h @@ -2,7 +2,7 @@ #include "../common_types.h" #include "../logger.h" -#include "fast_oss.h" +#include "stack_oss.h" // line logger class. should be used by the logger as an rvalue only. @@ -20,16 +20,19 @@ class line_logger public: line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled): _callback_logger(callback_logger), + _log_msg(), _oss(), - _level(msg_level), _enabled(enabled) { if(enabled) { + _log_msg.when = log_clock::now(); + _log_msg.msg_level = msg_level; callback_logger->_formatter->format_header(callback_logger->_logger_name, - msg_level, - log_clock::now(), + _log_msg.msg_level, + _log_msg.when, _oss); + _log_msg.header_size = _oss.size(); } } @@ -38,12 +41,12 @@ public: line_logger& operator=(const line_logger&) = delete; line_logger& operator=(line_logger&&) = delete; - // The move ctor should only be called on start of logging line, - // where no logging happened yet for this line so no need to copy the string from the other line_logger(line_logger&& other) : _callback_logger(other._callback_logger), + _log_msg(other._log_msg), + // The move ctor should only be called on start of logging line, + // where no logging happened yet for this line so no need to copy the oss from the other _oss(), - _level(other._level), _enabled(other._enabled) {} @@ -52,26 +55,28 @@ public: if (_enabled) { _oss << os::eol(); - _callback_logger->_log_it(_oss.buf(), _level); + _log_msg.msg_buf = _oss.buf(); + _callback_logger->_log_it(_log_msg); } } template - line_logger&& operator<<(const T& msg) + line_logger&& operator<<(const T& what) { if (_enabled) - _oss << msg; + _oss << what; return std::move(*this); } private: logger* _callback_logger; - details::fast_oss _oss; - level::level_enum _level; + c11log::log_msg _log_msg; + details::stack_oss _oss; bool _enabled; + }; } //Namespace details } // Namespace c11log diff --git a/include/c11log/details/fast_buf.h b/include/c11log/details/stack_buf.h similarity index 69% rename from include/c11log/details/fast_buf.h rename to include/c11log/details/stack_buf.h index 96d32882..f0774fb5 100644 --- a/include/c11log/details/fast_buf.h +++ b/include/c11log/details/stack_buf.h @@ -15,18 +15,18 @@ namespace details { template -class fast_buf +class stack_buf { public: - fast_buf():_stack_size(0) {} - ~fast_buf() {}; + stack_buf():_stack_size(0) {} + ~stack_buf() {}; - fast_buf(const bufpair_t& buf_to_copy):fast_buf() + stack_buf(const bufpair_t& buf_to_copy):stack_buf() { append(buf_to_copy); } - fast_buf(const fast_buf& other) + stack_buf(const stack_buf& other) { _stack_size = other._stack_size; if(!other._v.empty()) @@ -35,7 +35,7 @@ public: std::copy(other._stack_buf.begin(), other._stack_buf.begin()+_stack_size, _stack_buf.begin()); } - fast_buf(fast_buf&& other) + stack_buf(stack_buf&& other) { _stack_size = other._stack_size; if(!other._v.empty()) @@ -45,31 +45,31 @@ public: other.clear(); } - fast_buf& operator=(const fast_buf& other) = delete; - fast_buf& operator=(fast_buf&& other) = delete; + stack_buf& operator=(const stack_buf& other) = delete; + stack_buf& operator=(stack_buf&& other) = delete; - void append(const char* buf, std::size_t size) + void append(const char* buf, std::size_t buf_size) { //If we are aleady using _v, forget about the stack if(!_v.empty()) { - _v.insert(_v.end(), buf, buf+ size); + _v.insert(_v.end(), buf, buf+ buf_size); } //Try use the stack else { - if(_stack_size+size <= STACK_SIZE) + if(_stack_size+buf_size <= STACK_SIZE) { - std::memcpy(&_stack_buf[_stack_size], buf, size); - _stack_size+=size; + std::memcpy(&_stack_buf[_stack_size], buf, buf_size); + _stack_size+=buf_size; } //Not enough stack space. Copy all to _v else { - _v.reserve(_stack_size+size); + _v.reserve(_stack_size+buf_size); if(_stack_size) _v.insert(_v.end(), _stack_buf.begin(), _stack_buf.begin() +_stack_size); - _v.insert(_v.end(), buf, buf+size); + _v.insert(_v.end(), buf, buf+buf_size); } } } @@ -93,6 +93,14 @@ public: return bufpair_t(_stack_buf.data(), _stack_size); } + std::size_t size() + { + if(!_v.empty()) + return _v.size(); + else + return _stack_size; + } + private: std::vector _v; std::array _stack_buf; diff --git a/include/c11log/details/fast_oss.h b/include/c11log/details/stack_oss.h similarity index 64% rename from include/c11log/details/fast_oss.h rename to include/c11log/details/stack_oss.h index bb074c55..61c5c9a2 100644 --- a/include/c11log/details/fast_oss.h +++ b/include/c11log/details/stack_oss.h @@ -2,7 +2,7 @@ // Faster than ostringstream--returns its string by ref #include -#include "c11log/details/fast_buf.h" +#include "c11log/details/stack_buf.h" namespace c11log { @@ -12,7 +12,7 @@ namespace details class str_devicebuf:public std::streambuf { public: - using Base = std::streambuf; + using Base = std::streambuf; str_devicebuf() = default; ~str_devicebuf() = default; @@ -23,24 +23,29 @@ public: bufpair_t buf() { - return _fastbuf.get(); + return _stackbuf.get(); + } + + std::size_t size() + { + return _stackbuf.size(); } void clear() { - _fastbuf.clear(); + _stackbuf.clear(); } protected: // copy the give buffer into the accumulated fast buffer std::streamsize xsputn(const char_type* s, std::streamsize count) override { - _fastbuf.append(s, static_cast(count)); + _stackbuf.append(s, static_cast(count)); return count; } int_type overflow(int_type ch) override - { + { if (traits_type::not_eof(ch)) { char c = traits_type::to_char_type(ch); @@ -49,24 +54,29 @@ protected: return ch; } private: - fast_buf<192> _fastbuf; + stack_buf<192> _stackbuf; }; -class fast_oss:public std::ostream +class stack_oss:public std::ostream { public: - fast_oss():std::ostream(&_dev) {} - ~fast_oss() = default; + stack_oss():std::ostream(&_dev) {} + ~stack_oss() = default; - fast_oss(const fast_oss& other) = delete; - fast_oss(fast_oss&& other) = delete; - fast_oss& operator=(const fast_oss& other) = delete; + stack_oss(const stack_oss& other) = delete; + stack_oss(stack_oss&& other) = delete; + stack_oss& operator=(const stack_oss& other) = delete; bufpair_t buf() { return _dev.buf(); } + std::size_t size() + { + return _dev.size(); + } + void clear() { _dev.clear(); diff --git a/include/c11log/formatter.h b/include/c11log/formatter.h index 67be8a9f..9f431850 100644 --- a/include/c11log/formatter.h +++ b/include/c11log/formatter.h @@ -10,18 +10,17 @@ #include "common_types.h" #include "details/os.h" -#include "details/fast_oss.h" +#include "details/stack_oss.h" namespace c11log { namespace formatters { - class formatter { -public: - virtual void format_header(const std::string& logger_name, level::level_enum level, const log_clock::time_point& tp, std::ostream& dest) = 0; +public: + virtual void format_header(const std::string& logger_name, level::level_enum level, const log_clock::time_point& tp, std::ostream& output) = 0; }; @@ -29,17 +28,17 @@ class default_formatter: public formatter { public: // Format: [2013-12-29 01:04:42.900] [logger_name:Info] Message body - void format_header(const std::string& logger_name, level::level_enum level, const log_clock::time_point& tp, std::ostream& dest) override + void format_header(const std::string& logger_name, level::level_enum level, const log_clock::time_point& tp, std::ostream& output) override { - _format_time(tp, dest); + _format_time(tp, output); if(!logger_name.empty()) - dest << " [" << logger_name << ':' << c11log::level::to_str(level) << "] "; + output << " [" << logger_name << ':' << c11log::level::to_str(level) << "] "; else - dest << " [" << c11log::level::to_str(level) << "] "; + output << " [" << c11log::level::to_str(level) << "] "; } private: - void _format_time(const log_clock::time_point& tp, std::ostream &dest); + void _format_time(const log_clock::time_point& tp, std::ostream &output); }; @@ -48,7 +47,7 @@ private: } //namespace c11log // Format datetime like this: [2014-03-14 17:15:22] -inline void c11log::formatters::default_formatter::_format_time(const log_clock::time_point& tp, std::ostream &dest) +inline void c11log::formatters::default_formatter::_format_time(const log_clock::time_point& tp, std::ostream &output) { using namespace c11log::details::os; using namespace std::chrono; @@ -68,7 +67,7 @@ inline void c11log::formatters::default_formatter::_format_time(const log_clock: if(tp_time_t != s_cache_time_t) { auto tm_now = details::os::localtime(tp_time_t); - details::fast_oss time_oss; + details::stack_oss time_oss; time_oss.fill('0'); time_oss << '[' << tm_now.tm_year + 1900 << '-'; time_oss.width(2); @@ -88,5 +87,5 @@ inline void c11log::formatters::default_formatter::_format_time(const log_clock: std::memcpy(s_cache_str, buf.first, buf.second); s_cache_size = buf.second; } - dest.write(s_cache_str, s_cache_size); + output.write(s_cache_str, s_cache_size); } diff --git a/include/c11log/logger.h b/include/c11log/logger.h index 56426512..4b303823 100644 --- a/include/c11log/logger.h +++ b/include/c11log/logger.h @@ -11,7 +11,6 @@ #include "common_types.h" #include "sinks/base_sink.h" #include "details/factory.h" -#include "c11log/details/log_msg.h" //Thread safe, fast logger. @@ -69,7 +68,7 @@ private: sinks_vector_t _sinks; std::atomic_int _logger_level; - void _log_it(const bufpair_t& buf, const level::level_enum level); + void _log_it(const log_msg& msg); }; @@ -77,12 +76,10 @@ logger& get_logger(const std::string& name); } - // // Logger inline implementation // #include "details/line_logger.h" -#include "details/fast_buf.h" inline c11log::logger::logger(const std::string& name, formatter_ptr f, sinks_init_list sinks_list) : @@ -90,7 +87,7 @@ inline c11log::logger::logger(const std::string& name, formatter_ptr f, sinks_in _formatter(f), _sinks(sinks_list) { - //Seems that vs2013 doesnt support atomic member initialization in ctor, so its done here + //Seems that vs2013 doesnt support std::atomic member initialization, so its done here _logger_level = level::INFO; } @@ -149,10 +146,10 @@ inline bool c11log::logger::should_log(c11log::level::level_enum level) const return level >= _logger_level.load(); } -inline void c11log::logger::_log_it(const bufpair_t& buf, const level::level_enum level) +inline void c11log::logger::_log_it(const log_msg& msg) { for (auto &sink : _sinks) - sink->log(buf, level); + sink->log(msg); } // Static factory function diff --git a/include/c11log/sinks/async_sink.h b/include/c11log/sinks/async_sink.h index 2277378d..4eba5b2b 100644 --- a/include/c11log/sinks/async_sink.h +++ b/include/c11log/sinks/async_sink.h @@ -75,7 +75,7 @@ inline void c11log::sinks::async_sink::_thread_loop() bufpair_t buf(msg.data(), msg.size()); for (auto &sink : _sinks) { - sink->log(buf, static_cast(_level.load())); + sink->log(buf, level::INFO); if (!_active) return; } diff --git a/include/c11log/sinks/base_sink.h b/include/c11log/sinks/base_sink.h index 3f1bfcca..b5e4a93d 100644 --- a/include/c11log/sinks/base_sink.h +++ b/include/c11log/sinks/base_sink.h @@ -13,37 +13,39 @@ namespace sinks class base_sink { public: - base_sink() = default; - base_sink(level::level_enum l):_level(l) - { - }; + base_sink(): _enabled(true) {} virtual ~base_sink() = default; base_sink(const base_sink&) = delete; base_sink& operator=(const base_sink&) = delete; - void log(const bufpair_t &msg, level::level_enum level) + void log(const log_msg& msg) { - if (level >= _level) + if (_enabled) { _sink_it(msg); } }; - void set_level(level::level_enum level) + void enable(bool enabled) { - _level = level; + _enabled = enabled; + } + + bool is_enabled() + { + return _enabled.load(); } protected: - virtual void _sink_it(const bufpair_t& msg) = 0; - std::atomic _level {level::INFO}; + virtual void _sink_it(const log_msg& msg) = 0; + std::atomic _enabled; }; class null_sink:public base_sink { protected: - void _sink_it(const bufpair_t& ) override + void _sink_it(const log_msg&) override { } }; diff --git a/include/c11log/sinks/console_sinks.h b/include/c11log/sinks/console_sinks.h index 08ec2090..a8a45af8 100644 --- a/include/c11log/sinks/console_sinks.h +++ b/include/c11log/sinks/console_sinks.h @@ -19,10 +19,10 @@ public: virtual ~console_sink() = default; protected: - virtual void _sink_it(const bufpair_t& msg) override + virtual void _sink_it(const log_msg& msg) override { std::lock_guard lock(_mutex); - _ostream.write(msg.first, msg.second); + _ostream.write(msg.msg_buf.first, msg.msg_buf.second); } std::ostream& _ostream; diff --git a/include/c11log/sinks/file_sinks.h b/include/c11log/sinks/file_sinks.h index 6001903b..94c43577 100644 --- a/include/c11log/sinks/file_sinks.h +++ b/include/c11log/sinks/file_sinks.h @@ -27,10 +27,10 @@ public: { } protected: - void _sink_it(const bufpair_t& msg) override + void _sink_it(const log_msg& msg) override { std::lock_guard lock(_mutex); - _flush_helper.write(_ofstream, msg); + _flush_helper.write(_ofstream, msg.msg_buf); } private: std::mutex _mutex; @@ -60,16 +60,17 @@ public: } protected: - void _sink_it(const bufpair_t& msg) override + void _sink_it(const log_msg& msg) override { std::lock_guard lock(_mutex); - _current_size += msg.second; + + _current_size += msg.msg_buf.second; if (_current_size > _max_size) { _rotate(); - _current_size = msg.second; + _current_size = msg.msg_buf.second; } - _flush_helper.write(_ofstream, msg); + _flush_helper.write(_ofstream, msg.msg_buf); } @@ -133,7 +134,7 @@ public: } protected: - void _sink_it(const bufpair_t& msg) override + void _sink_it(const log_msg& msg) override { std::lock_guard lock(_mutex); if (std::chrono::system_clock::now() >= _midnight_tp) @@ -142,7 +143,7 @@ protected: _ofstream.open(_calc_filename(_base_filename, _extension)); _midnight_tp = _calc_midnight_tp(); } - _flush_helper.write(_ofstream, msg); + _flush_helper.write(_ofstream, msg.msg_buf); } private: