flush every period
This commit is contained in:
		
							parent
							
								
									6f4c780089
								
							
						
					
					
						commit
						ddcf45d65f
					
				@ -2,7 +2,7 @@
 | 
			
		||||
//
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <functional>
 | 
			
		||||
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
#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<sinks::rotating_file_sink>("log", "txt", 1024*1024*50 , 5, seconds(1));
 | 
			
		||||
    auto &logger2 = c11log::get_logger("logger2");
 | 
			
		||||
    logger2.add_sink(fsink2);
 | 
			
		||||
    //logger2.add_sink(std::make_shared<sinks::null_sink>());
 | 
			
		||||
 | 
			
		||||
    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<duration<double>> (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<sinks::null_sink>();
 | 
			
		||||
    auto stdout_sink = std::make_shared<sinks::stdout_sink>();
 | 
			
		||||
    auto async = std::make_shared<sinks::async_sink>(qsize);
 | 
			
		||||
    auto fsink = std::make_shared<sinks::rotating_file_sink>("log", "txt", 1024*1024*50 , 5, 1000);
 | 
			
		||||
    auto fsink = std::make_shared<sinks::rotating_file_sink>("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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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 
 | 
			
		||||
 | 
			
		||||
@ -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<void() >& fn)
 | 
			
		||||
{
 | 
			
		||||
    using namespace std::chrono;
 | 
			
		||||
 | 
			
		||||
@ -58,7 +58,7 @@ public:
 | 
			
		||||
    // If the queue is full, block the calling thread until there is room.
 | 
			
		||||
    template<typename TT>
 | 
			
		||||
    void push(TT&& item) {
 | 
			
		||||
        while (!push(std::forward<TT>(item), one_hour));
 | 
			
		||||
        while (!push(std::forward<TT>(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);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,24 +1,33 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
// 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;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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) {};
 | 
			
		||||
 | 
			
		||||
@ -4,15 +4,15 @@
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
 | 
			
		||||
#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<std::string(const std::string& logger_name, const std::string&, level::level_enum, const time_point&)> format_fn;
 | 
			
		||||
 | 
			
		||||
typedef std::function<std::string(const std::string& logger_name, const std::string&, level::level_enum, const c11log::log_clock::time_point&)> 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];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if(duration_cast<milliseconds>(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,
 | 
			
		||||
    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);
 | 
			
		||||
        last_tp = tp;
 | 
			
		||||
    }
 | 
			
		||||
    dest << timestamp_cache;
 | 
			
		||||
 | 
			
		||||
    dest.write(buff, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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];
 | 
			
		||||
}
 | 
			
		||||
@ -8,15 +8,18 @@
 | 
			
		||||
#include<atomic>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
#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:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
#include<atomic>
 | 
			
		||||
 | 
			
		||||
#include "../formatter.h"
 | 
			
		||||
#include "../level.h"
 | 
			
		||||
#include "../common_types.h"
 | 
			
		||||
 | 
			
		||||
namespace c11log {
 | 
			
		||||
namespace sinks {
 | 
			
		||||
 | 
			
		||||
@ -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:
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user