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) {};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
@ -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;
|
||||
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user