flush every period

This commit is contained in:
gabime 2014-03-01 14:06:58 +02:00
parent 6f4c780089
commit ddcf45d65f
11 changed files with 105 additions and 76 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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);
};
}

View File

@ -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;
};
}
}

View File

@ -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) {};

View File

@ -1,18 +1,18 @@
#pragma once
#include<string>
#include<chrono>
#include<functional>
#include <string>
#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];
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<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,
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);
}

View File

@ -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];
}

View File

@ -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:

View File

@ -4,7 +4,7 @@
#include<atomic>
#include "../formatter.h"
#include "../level.h"
#include "../common_types.h"
namespace c11log {
namespace sinks {

View File

@ -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;
};
}