logger refactoring to init lists and mutex remove

This commit is contained in:
gabime 2014-03-08 16:18:57 +02:00
parent 0caa2dd1e8
commit a6d1ea77ee
8 changed files with 106 additions and 118 deletions

View File

@ -9,62 +9,37 @@
#include "utils.h" #include "utils.h"
std::atomic<uint64_t> log_count; using std::cout;
std::atomic<bool> active; using std::endl;
using namespace std::chrono;
using std::chrono::seconds; using namespace c11log;
using namespace utils;
void logging_thread()
{
auto &logger = c11log::get_logger("async");
while(active) {
logger.info()<<"Hello logger!";
++log_count;
}
}
void testlog(int threads)
{
active = true;
for(int i = 0; i < threads; i++)
new std::thread(std::bind(logging_thread));
while(active) {
using std::endl;
using std::cout;
using utils::format;
log_count = 0;
std::this_thread::sleep_for(seconds(1));
cout << "Logs/sec =\t" << format(log_count.load()) << endl;
}
}
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
if(argc || argv) {}; if(argc || argv) {};
using namespace std::chrono;
using namespace c11log;
using namespace utils;
using std::cout;
using std::endl;
auto fsink = std::make_shared<sinks::rotating_file_sink>("log", "txt", 1024*1024*50 , 5, seconds(1)); auto fsink = std::make_shared<sinks::rotating_file_sink>("log", "txt", 1024*1024*50 , 5, seconds(1));
auto &my_logger = get_logger("example"); //auto &my_logger = get_logger("example");
auto null_sink = std::make_shared<sinks::null_sink>(); auto null_sink = std::make_shared<sinks::null_sink>();
//auto async = std::make_shared<sinks::async_sink>(1000); //auto async = std::make_shared<sinks::async_sink>(1000);
//my_logger.add_sink(fsink); //my_logger.add_sink(fsink);
my_logger.add_sink(null_sink); //my_logger.add_sink(null_sink);
auto &cout_logger = get_logger("cout");
cout_logger.add_sink(sinks::stdout_sink());
cout_logger.info() << "Hello cout logger!"; logger cout_logger (
"cout",
{null_sink, sinks::stdout_sink(), fsink});
cout_logger.info() << "Hello cout logger!";
logger log2 {sinks::stdout_sink()};
log2.error() << "Cool shit" << "!!!";
return 0;
/*
auto start = system_clock::now(); auto start = system_clock::now();
const unsigned int howmany = 5000000; const unsigned int howmany = 5000000;
@ -80,7 +55,7 @@ int main(int argc, char* argv[])
return 0; return 0;
*/
/* /*
if(argc !=3) { if(argc !=3) {
std::cerr << "Usage: " << argv[0] << " qsize, threads" << std::endl; std::cerr << "Usage: " << argv[0] << " qsize, threads" << std::endl;

View File

@ -21,7 +21,7 @@ const char* to_str(level_enum l);
} }
} }
static const char* level_names[] { "Debug", "Info", "Warning", "Error", "Fatal" }; static const char* level_names[] { "debug", "info", "warning", "error", "fatal" };
inline const char* c11log::level::to_str(c11log::level::level_enum l) inline const char* c11log::level::to_str(c11log::level::level_enum l)
{ {
return level_names[l]; return level_names[l];

View File

@ -13,29 +13,45 @@ namespace details
class factory class factory
{ {
public: public:
typedef std::shared_ptr<c11log::logger> logger_ptr; using logger_ptr = std::shared_ptr<c11log::logger>;
typedef std::unordered_map<std::string, logger_ptr> logger_map; using logger_map = std::unordered_map<std::string, logger_ptr>;
logger_ptr get_logger(const std::string &name); void add_logger(const std::string& name, logger_ptr);
logger_ptr get_logger(const std::string &name);
static c11log::details::factory& instance(); static c11log::details::factory& instance();
private: private:
std::mutex _loggers_mutex;
logger_map _loggers; logger_map _loggers;
std::mutex _loggers_mutex;
}; };
} }
} }
inline void c11log::details::factory::add_logger(const std::string& name, logger_ptr logger_p)
{
std::lock_guard<std::mutex> lock(_loggers_mutex);
_loggers.insert(logger_map::value_type(name, logger_p));
}
inline c11log::details::factory::logger_ptr c11log::details::factory::get_logger(const std::string &name) inline c11log::details::factory::logger_ptr c11log::details::factory::get_logger(const std::string &name)
{ {
std::lock_guard<std::mutex> lock(_loggers_mutex); std::lock_guard<std::mutex> lock(_loggers_mutex);
auto found = _loggers.find(name);
auto found = _loggers.find(name);
if (found != _loggers.end())
return found->second;
else
return logger_ptr(nullptr);
/*
auto found = _loggers.find(name);
if (found == _loggers.end()) { if (found == _loggers.end()) {
auto new_logger_ptr = std::make_shared<c11log::logger>(name); auto new_logger_ptr = std::make_shared<c11log::logger>(name);
_loggers.insert(std::make_pair(name, new_logger_ptr)); _loggers.insert(std::make_pair(name, new_logger_ptr));
return new_logger_ptr; return new_logger_ptr;
} else { } else {
return found->second; return found->second;
} }*/
} }
inline c11log::details::factory & c11log::details::factory::instance() inline c11log::details::factory & c11log::details::factory::instance()

View File

@ -3,11 +3,15 @@
#include "../common_types.h" #include "../common_types.h"
#include "../logger.h" #include "../logger.h"
#include "fast_oss.h" #include "fast_oss.h"
#include <iostream>
// line logger class. should be used by the logger as an rvalue only.
// aggregates logging string until the end of the line and then calls the logger upon destruction
namespace c11log namespace c11log
{ {
class logger; //class logger;
namespace details namespace details
{ {
@ -19,24 +23,27 @@ public:
_oss(), _oss(),
_level(msg_level), _level(msg_level),
_enabled(enabled) { _enabled(enabled) {
callback_logger->_formatter->format_header(callback_logger->_logger_name, if(enabled) {
msg_level, callback_logger->_formatter->format_header(callback_logger->_logger_name,
log_clock::now(), msg_level,
_oss); log_clock::now(),
_oss);
}
} }
// No copy intended. Only move // No copy intended. Only move
line_logger(const line_logger& other) = delete; line_logger(const line_logger& other) = delete;
line_logger& operator=(const line_logger&) = delete;
line_logger& operator=(line_logger&&) = delete;
line_logger(line_logger&& other) : line_logger(line_logger&& other) :
_callback_logger(other._callback_logger), _callback_logger(other._callback_logger),
// 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
_oss(), _oss(),
_level(other._level) { _level(other._level) {
}; };
line_logger& operator=(const line_logger&) = delete;
line_logger& operator=(line_logger&&) = delete;
~line_logger() { ~line_logger() {
if (_enabled) { if (_enabled) {
_oss << '\n'; _oss << '\n';
@ -46,15 +53,14 @@ public:
template<typename T> template<typename T>
line_logger& operator<<(const T& msg) { line_logger&& operator<<(const T& msg) && {
if (_enabled) if (_enabled)
_oss << msg; _oss << msg;
return *this; return std::move(*this);
} }
private: private:
logger* _callback_logger; logger* _callback_logger;
//std::ostringstream _oss;
details::fast_oss _oss; details::fast_oss _oss;
level::level_enum _level; level::level_enum _level;
bool _enabled; bool _enabled;

View File

@ -33,7 +33,11 @@ public:
// Format: [2013-12-29 01:04:42.900] [logger_name:Info] Message body // 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& dest) override {
_format_time(tp, dest); _format_time(tp, dest);
dest << " [" << logger_name << ":" << c11log::level::to_str(level) << "] "; if(!logger_name.empty())
dest << " [" << logger_name << ":" << c11log::level::to_str(level) << "] ";
else
dest << " [" << c11log::level::to_str(level) << "] ";
} }
private: private:
void _format_time(const log_clock::time_point& tp, std::ostream &dest); void _format_time(const log_clock::time_point& tp, std::ostream &dest);

View File

@ -12,10 +12,12 @@
#include "sinks/base_sink.h" #include "sinks/base_sink.h"
#include "details/factory.h" #include "details/factory.h"
//Thread safe, fast logger.
//All initialization is done in ctor only, so we get away lot of locking
namespace c11log namespace c11log
{ {
namespace details namespace details
{ {
class line_logger; class line_logger;
@ -26,33 +28,43 @@ class logger
{ {
public: public:
typedef std::shared_ptr<sinks::base_sink> sink_ptr_t; using sink_ptr = std::shared_ptr<sinks::base_sink>;
typedef std::vector<sink_ptr_t> sinks_vector_t; using formatter_ptr = std::shared_ptr<c11log::formatters::formatter>;
using sinks_vector_t = std::vector<sink_ptr>;
using sinks_init_list = std::initializer_list<sink_ptr>;
explicit logger(const std::string& name) :
logger(const std::string& name, formatter_ptr f, sinks_init_list sinks_list) :
_logger_name(name), _logger_name(name),
_formatter(new formatters::default_formatter()), _formatter(f),
_sinks(), _sinks(sinks_list) {
_mutex() {
//Seems that vs2013 doesnt support atomic member initialization in ctor, so its done here //Seems that vs2013 doesnt support atomic member initialization in ctor, so its done here
_atomic_level = level::INFO; _atomic_level = level::INFO;
} }
logger(const std::string& name, sinks_init_list sinks_list) :
logger(name, std::make_shared<formatters::default_formatter>(), sinks_list) {}
logger(sinks_init_list sinks_list) :
logger("", std::make_shared<formatters::default_formatter>(), sinks_list) {}
~logger() = default; ~logger() = default;
//Non copybale in anyway
logger(const logger&) = delete; logger(const logger&) = delete;
logger(logger&&) = delete;
logger& operator=(const logger&) = delete; logger& operator=(const logger&) = delete;
logger& operator=(logger&&) = delete;
void set_name(const std::string& name); void set_level(c11log::level::level_enum);
const std::string& get_name();
void add_sink(sink_ptr_t sink_ptr);
void remove_sink(sink_ptr_t sink_ptr);
void set_formatter(std::unique_ptr<formatters::formatter> formatter);
void set_level(c11log::level::level_enum level);
c11log::level::level_enum get_level() const; c11log::level::level_enum get_level() const;
bool should_log(c11log::level::level_enum level) const;
details::line_logger log(level::level_enum level); const std::string& get_name() const;
bool should_log(c11log::level::level_enum) const;
details::line_logger log(level::level_enum);
details::line_logger debug(); details::line_logger debug();
details::line_logger info(); details::line_logger info();
details::line_logger warn(); details::line_logger warn();
@ -63,9 +75,8 @@ private:
friend details::line_logger; friend details::line_logger;
std::string _logger_name = ""; std::string _logger_name = "";
std::unique_ptr<c11log::formatters::formatter> _formatter; formatter_ptr _formatter;
sinks_vector_t _sinks; sinks_vector_t _sinks;
std::mutex _mutex;
std::atomic_int _atomic_level; std::atomic_int _atomic_level;
void _log_it(const std::string& msg, const level::level_enum level); void _log_it(const std::string& msg, const level::level_enum level);
@ -107,35 +118,12 @@ inline c11log::details::line_logger c11log::logger::fatal()
return log(c11log::level::FATAL); return log(c11log::level::FATAL);
} }
inline void c11log::logger::set_name(const std::string& name)
{
std::lock_guard<std::mutex> lock(_mutex);
_logger_name = name;
}
inline const std::string& c11log::logger::get_name() inline const std::string& c11log::logger::get_name() const
{ {
std::lock_guard<std::mutex> lock(_mutex);
return _logger_name; return _logger_name;
} }
inline void c11log::logger::add_sink(sink_ptr_t sink_ptr)
{
std::lock_guard<std::mutex> lock(_mutex);
_sinks.push_back(sink_ptr);
}
inline void c11log::logger::remove_sink(sink_ptr_t sink_ptr)
{
std::lock_guard<std::mutex> lock(_mutex);
_sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink_ptr), _sinks.end());
}
inline void c11log::logger::set_formatter(std::unique_ptr<formatters::formatter> formatter)
{
std::lock_guard<std::mutex> lock(_mutex);
_formatter = std::move(formatter);
}
inline void c11log::logger::set_level(c11log::level::level_enum level) inline void c11log::logger::set_level(c11log::level::level_enum level)
{ {
@ -143,7 +131,7 @@ inline void c11log::logger::set_level(c11log::level::level_enum level)
} }
inline c11log::level::level_enum c11log::logger::get_level() const inline c11log::level::level_enum c11log::logger::get_level() const
{ {
return static_cast<c11log::level::level_enum>(_atomic_level.load()); return static_cast<c11log::level::level_enum>(_atomic_level.load());
} }
@ -153,14 +141,13 @@ inline bool c11log::logger::should_log(c11log::level::level_enum level) const
} }
inline void c11log::logger::_log_it(const std::string& msg, const level::level_enum level) inline void c11log::logger::_log_it(const std::string& msg, const level::level_enum level)
{ {
std::lock_guard<std::mutex> lock(_mutex);
for (auto &sink : _sinks) for (auto &sink : _sinks)
sink->log(msg, level); sink->log(msg, level);
} }
// Static factory function // Static factory function
inline c11log::logger& c11log::get_logger(const std::string& name) inline c11log::logger& c11log::get_logger(const std::string& name)
{ {
return *(c11log::details::factory::instance().get_logger(name)); return *(c11log::details::factory::instance().get_logger(name));
} }

View File

@ -20,8 +20,8 @@ public:
explicit async_sink(const size_type max_queue_size); explicit async_sink(const size_type max_queue_size);
~async_sink(); ~async_sink();
void add_sink(logger::sink_ptr_t sink); void add_sink(logger::sink_ptr sink);
void remove_sink(logger::sink_ptr_t sink_ptr); void remove_sink(logger::sink_ptr sink_ptr);
//Wait to remaining items (if any) in the queue to be written and shutdown //Wait to remaining items (if any) in the queue to be written and shutdown
void shutdown(const std::chrono::seconds& timeout); void shutdown(const std::chrono::seconds& timeout);
@ -78,12 +78,12 @@ inline void c11log::sinks::async_sink::_thread_loop()
} }
} }
inline void c11log::sinks::async_sink::add_sink(logger::sink_ptr_t sink) inline void c11log::sinks::async_sink::add_sink(logger::sink_ptr sink)
{ {
_sinks.push_back(sink); _sinks.push_back(sink);
} }
inline void c11log::sinks::async_sink::remove_sink(logger::sink_ptr_t sink_ptr) inline void c11log::sinks::async_sink::remove_sink(logger::sink_ptr sink_ptr)
{ {
_sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink_ptr), _sinks.end()); _sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink_ptr), _sinks.end());
} }

View File

@ -31,14 +31,14 @@ protected:
inline std::shared_ptr<console_sink>& stdout_sink () inline std::shared_ptr<console_sink>& stdout_sink ()
{ {
static auto inst = std::make_shared<console_sink>(std::cout); static auto inst = std::make_shared<console_sink>(std::cout);
return inst; return inst;
} }
inline std::shared_ptr<console_sink>& stderr_sink () inline std::shared_ptr<console_sink>& stderr_sink ()
{ {
static auto inst = std::make_shared<console_sink>(std::cerr); static auto inst = std::make_shared<console_sink>(std::cerr);
return inst; return inst;
} }