From ddcf45d65f029ec900f99cfe23b4edb58c77a515 Mon Sep 17 00:00:00 2001 From: gabime Date: Sat, 1 Mar 2014 14:06:58 +0200 Subject: [PATCH] flush every period --- example/example.cpp | 37 +++++++++++++++++--- example/makefile | 2 +- example/utils.h | 10 ++++++ include/c11log/details/blocking_queue.h | 6 ++-- include/c11log/details/flush_helper.h | 21 +++++++---- include/c11log/details/line_logger.h | 4 +-- include/c11log/formatter.h | 46 +++++++++++-------------- include/c11log/level.h | 21 ----------- include/c11log/logger.h | 5 ++- include/c11log/sinks/base_sink.h | 2 +- include/c11log/sinks/file_sinks.h | 27 +++++++++------ 11 files changed, 105 insertions(+), 76 deletions(-) delete mode 100644 include/c11log/level.h diff --git a/example/example.cpp b/example/example.cpp index bf08ab72..6232d970 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -2,7 +2,7 @@ // #include #include - +#include #include "c11log/logger.h" #include "c11log/sinks/async_sink.h" #include "c11log/sinks/file_sinks.h" @@ -47,7 +47,32 @@ void testlog(int threads) int main(int argc, char* argv[]) { + using namespace std::chrono; + using namespace c11log; + using namespace utils; + using std::cout; + using std::endl; + + auto fsink2 = std::make_shared("log", "txt", 1024*1024*50 , 5, seconds(1)); + auto &logger2 = c11log::get_logger("logger2"); + logger2.add_sink(fsink2); + //logger2.add_sink(std::make_shared()); + + auto start = system_clock::now(); + const unsigned int howmany = 10000000; + for(unsigned int i = 0; i < howmany ; i++) + logger2.info() << "Hello logger " << i; + + 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; + + + return 0; + if(argc !=3) { std::cerr << "Usage: " << argv[0] << " qsize, threads" << std::endl; @@ -56,16 +81,18 @@ int main(int argc, char* argv[]) int qsize = atoi(argv[1]); int threads = atoi(argv[2]); - using namespace c11log; + auto null_sink = std::make_shared(); auto stdout_sink = std::make_shared(); auto async = std::make_shared(qsize); - auto fsink = std::make_shared("log", "txt", 1024*1024*50 , 5, 1000); + auto fsink = std::make_shared("log", "txt", 1024*1024*50 , 5, std::chrono::milliseconds(1000)); async->add_sink(fsink); - auto &logger = c11log::get_logger("async"); - logger.add_sink(fsink); + //auto &logger = c11log::get_logger("async"); + //logger.add_sink(fsink); + + testlog(threads); } diff --git a/example/makefile b/example/makefile index 330d3af0..b102c8f4 100644 --- a/example/makefile +++ b/example/makefile @@ -1,4 +1,4 @@ -CXX = g++ +CXX = ccache g++ CXXFLAGS = -march=native -Wall -Wextra -Wshadow -pedantic -std=c++11 -pthread -I../include CXX_RELEASE_FLAGS = -O3 -flto CXX_DEBUG_FLAGS= -g diff --git a/example/utils.h b/example/utils.h index e8a9e935..2eaa592b 100644 --- a/example/utils.h +++ b/example/utils.h @@ -19,6 +19,16 @@ std::string format(const T& value) return ss.str(); } +template<> +std::string format(const double & value) +{ + static std::locale loc(""); + std::stringstream ss; + ss.imbue(loc); + ss << std::fixed << std::setprecision(1) << value; + return ss.str(); +} + inline void bench(const std::string& fn_name, const std::chrono::milliseconds &duration, const std::function& fn) { using namespace std::chrono; diff --git a/include/c11log/details/blocking_queue.h b/include/c11log/details/blocking_queue.h index 2ac8bbc0..cea541a2 100644 --- a/include/c11log/details/blocking_queue.h +++ b/include/c11log/details/blocking_queue.h @@ -58,7 +58,7 @@ public: // If the queue is full, block the calling thread until there is room. template void push(TT&& item) { - while (!push(std::forward(item), one_hour)); + while (!push(std::forward(item), _one_hour)); } // Pop a copy of the front item in the queue into the given item ref. @@ -85,7 +85,7 @@ public: // Pop a copy of the front item in the queue into the given item ref. // If the queue is empty, block the calling thread util there is item to pop. void pop(T& item) { - while (!pop(item, one_hour)); + while (!pop(item, _one_hour)); } // Clear the queue @@ -103,7 +103,7 @@ private: std::mutex _mutex; std::condition_variable _item_pushed_cond; std::condition_variable _item_popped_cond; - static constexpr auto one_hour = std::chrono::hours(1); + static constexpr auto _one_hour = std::chrono::hours(1); }; } diff --git a/include/c11log/details/flush_helper.h b/include/c11log/details/flush_helper.h index 41ece7d3..f179891d 100644 --- a/include/c11log/details/flush_helper.h +++ b/include/c11log/details/flush_helper.h @@ -1,24 +1,33 @@ #pragma once - +#include +#include // Flush to file every X writes.. namespace c11log { namespace details { class file_flush_helper { public: - explicit file_flush_helper(std::size_t flush_every): _flush_every(flush_every), _write_counter(0) {}; + explicit file_flush_helper(const std::chrono::milliseconds &flush_every): _flush_every(flush_every), _last_flush() {}; void write(std::ofstream& ofs, const std::string& msg) { + + ofs << msg; - if(++_write_counter >= _flush_every) { + //If zero - flush every time + if(_flush_every == std::chrono::milliseconds::min()) { ofs.flush(); - _write_counter = 0; + } else { + auto now = std::chrono::system_clock::now(); + if(now - _last_flush >= _flush_every) { + ofs.flush(); + _last_flush = now; + } } } private: - std::size_t _flush_every; - std::size_t _write_counter; + std::chrono::milliseconds _flush_every; + std::chrono::system_clock::time_point _last_flush; }; } } diff --git a/include/c11log/details/line_logger.h b/include/c11log/details/line_logger.h index b0222843..43a7b7a9 100644 --- a/include/c11log/details/line_logger.h +++ b/include/c11log/details/line_logger.h @@ -1,6 +1,6 @@ #pragma once -#include "../level.h" +#include "../common_types.h" #include "../logger.h" #include "fast_oss.h" @@ -16,7 +16,7 @@ public: _level(msg_level) { callback_logger->_formatter->format_header(callback_logger->_logger_name, msg_level, - c11log::formatters::clock::now(), + log_clock::now(), _oss); } line_logger(logger*):_callback_logger(nullptr) {}; diff --git a/include/c11log/formatter.h b/include/c11log/formatter.h index af8324b0..fa424293 100644 --- a/include/c11log/formatter.h +++ b/include/c11log/formatter.h @@ -1,18 +1,18 @@ #pragma once -#include -#include -#include +#include +#include +#include #include +#include -#include "level.h" +#include "common_types.h" #include "details/os.h" namespace c11log { namespace formatters { -typedef std::chrono::system_clock clock; -typedef clock::time_point time_point; -typedef std::function format_fn; + +typedef std::function format_fn; std::string to_hex(const unsigned char* buf, std::size_t size); @@ -21,19 +21,19 @@ class formatter { public: formatter() {} virtual ~formatter() {} - virtual void format_header(const std::string& logger_name, level::level_enum level, const time_point& tp, std::ostream& dest) = 0; + virtual void format_header(const std::string& logger_name, level::level_enum level, const log_clock::time_point& tp, std::ostream& dest) = 0; }; 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 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& dest) override { _format_time(tp, dest); dest << " [" << logger_name << ":" << c11log::level::to_str(level) << "] "; } private: - void _format_time(const time_point& tp, std::ostream &dest); + void _format_time(const log_clock::time_point& tp, std::ostream &dest); }; } //namespace formatter @@ -41,23 +41,19 @@ private: -inline void c11log::formatters::default_formatter::_format_time(const time_point& tp, std::ostream &dest) +inline void c11log::formatters::default_formatter::_format_time(const log_clock::time_point& tp, std::ostream &dest) { using namespace std::chrono; - static thread_local c11log::formatters::time_point last_tp; - static thread_local char timestamp_cache[64]; + auto tm = details::os::localtime(log_clock::to_time_t(tp)); + char buff[64]; + int size = snprintf(buff, sizeof(buff), "[%d-%02d-%02d %02d:%02d:%02d]", + tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_mday, + tm.tm_hour, + tm.tm_min, + tm.tm_sec); - - if(duration_cast(tp-last_tp).count() > 950) { - auto tm = details::os::localtime(clock::to_time_t(tp)); - sprintf(timestamp_cache, "[%d-%02d-%02d %02d:%02d:%02d]", tm.tm_year + 1900, - tm.tm_mon + 1, - tm.tm_mday, - tm.tm_hour, - tm.tm_min, - tm.tm_sec); - last_tp = tp; - } - dest << timestamp_cache; + dest.write(buff, size); } diff --git a/include/c11log/level.h b/include/c11log/level.h deleted file mode 100644 index d04ba6c8..00000000 --- a/include/c11log/level.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -namespace c11log { -namespace level { -typedef enum { - DEBUG, - INFO, - WARNING, - ERROR, - FATAL, - NONE = 99 -} level_enum; -const char* to_str(level_enum l); -} -} - -static const char* level_names[] { "Debug", "Info", "Warning", "Error", "Fatal" }; -inline const char* c11log::level::to_str(c11log::level::level_enum l) -{ - return level_names[l]; -} \ No newline at end of file diff --git a/include/c11log/logger.h b/include/c11log/logger.h index b8c62754..e68ba25e 100644 --- a/include/c11log/logger.h +++ b/include/c11log/logger.h @@ -8,15 +8,18 @@ #include #include -#include "level.h" +#include "common_types.h" #include "sinks/base_sink.h" #include "details/factory.h" namespace c11log { + + namespace details { class line_logger; } + class logger { public: diff --git a/include/c11log/sinks/base_sink.h b/include/c11log/sinks/base_sink.h index f5846e8d..dbe3bdb0 100644 --- a/include/c11log/sinks/base_sink.h +++ b/include/c11log/sinks/base_sink.h @@ -4,7 +4,7 @@ #include #include "../formatter.h" -#include "../level.h" +#include "../common_types.h" namespace c11log { namespace sinks { diff --git a/include/c11log/sinks/file_sinks.h b/include/c11log/sinks/file_sinks.h index 63d16cb4..4caa439f 100644 --- a/include/c11log/sinks/file_sinks.h +++ b/include/c11log/sinks/file_sinks.h @@ -14,10 +14,12 @@ namespace sinks { */ class simple_file_sink : public base_sink { public: - explicit simple_file_sink(const std::string &filename, const std::string& extension, size_t flush_after=1) + explicit simple_file_sink(const std::string &filename, + const std::string& extension, + const std::chrono::milliseconds &flush_every=std::chrono::milliseconds::zero()) : _mutex(), - _ofstream(filename + "." + extension, std::ofstream::app), - _flush_helper(flush_after) { + _ofstream(filename + "." + extension, std::ofstream::binary|std::ofstream::app), + _flush_helper(flush_every) { } protected: void _sink_it(const std::string& msg) override { @@ -36,15 +38,17 @@ private: */ class rotating_file_sink : public base_sink { public: - rotating_file_sink(const std::string &base_filename, const std::string &extension, size_t max_size, size_t max_files, size_t flush_after=1): + rotating_file_sink(const std::string &base_filename, const std::string &extension, + size_t max_size, size_t max_files, + const std::chrono::milliseconds &flush_every = std::chrono::milliseconds::zero()): _base_filename(base_filename), _extension(extension), _max_size(max_size), _max_files(max_files), _current_size(0), _mutex(), - _ofstream(_calc_filename(_base_filename, 0, _extension)), - _flush_helper(flush_after) { + _ofstream(_calc_filename(_base_filename, 0, _extension), std::ofstream::binary), + _flush_helper(flush_every) { } protected: @@ -102,14 +106,15 @@ private: */ class daily_file_sink:public base_sink { public: - explicit daily_file_sink(const std::string& base_filename, const std::string& extension, size_t flush_after=1): + explicit daily_file_sink(const std::string& base_filename, + const std::string& extension, + const std::chrono::milliseconds &flush_every = std::chrono::milliseconds::zero()): _base_filename(base_filename), _extension(extension), _midnight_tp (_calc_midnight_tp() ), _mutex(), - _ofstream(_calc_filename(_base_filename, _extension), std::ofstream::app), - _flush_helper(flush_after) - { + _ofstream(_calc_filename(_base_filename, _extension), std::ofstream::binary|std::ofstream::app), + _flush_helper(flush_every) { } protected: @@ -147,7 +152,7 @@ private: std::chrono::system_clock::time_point _midnight_tp; std::mutex _mutex; std::ofstream _ofstream; - details::file_flush_helper _flush_helper; + details::file_flush_helper _flush_helper; }; }