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"
std::atomic<uint64_t> log_count;
std::atomic<bool> active;
using std::chrono::seconds;
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;
}
}
using std::cout;
using std::endl;
using namespace std::chrono;
using namespace c11log;
using namespace utils;
int main(int argc, char* 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 &my_logger = get_logger("example");
//auto &my_logger = get_logger("example");
auto null_sink = std::make_shared<sinks::null_sink>();
//auto async = std::make_shared<sinks::async_sink>(1000);
//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();
const unsigned int howmany = 5000000;
@ -80,7 +55,7 @@ int main(int argc, char* argv[])
return 0;
*/
/*
if(argc !=3) {
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)
{
return level_names[l];

View File

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

View File

@ -3,11 +3,15 @@
#include "../common_types.h"
#include "../logger.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
{
class logger;
//class logger;
namespace details
{
@ -19,24 +23,27 @@ public:
_oss(),
_level(msg_level),
_enabled(enabled) {
callback_logger->_formatter->format_header(callback_logger->_logger_name,
msg_level,
log_clock::now(),
_oss);
if(enabled) {
callback_logger->_formatter->format_header(callback_logger->_logger_name,
msg_level,
log_clock::now(),
_oss);
}
}
// No copy intended. Only move
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) :
_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(),
_level(other._level) {
};
line_logger& operator=(const line_logger&) = delete;
line_logger& operator=(line_logger&&) = delete;
~line_logger() {
if (_enabled) {
_oss << '\n';
@ -46,15 +53,14 @@ public:
template<typename T>
line_logger& operator<<(const T& msg) {
line_logger&& operator<<(const T& msg) && {
if (_enabled)
_oss << msg;
return *this;
return std::move(*this);
}
private:
logger* _callback_logger;
//std::ostringstream _oss;
details::fast_oss _oss;
level::level_enum _level;
bool _enabled;

View File

@ -33,7 +33,11 @@ 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 log_clock::time_point& tp, std::ostream& dest) override {
_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:
void _format_time(const log_clock::time_point& tp, std::ostream &dest);

View File

@ -12,10 +12,12 @@
#include "sinks/base_sink.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 details
{
class line_logger;
@ -26,33 +28,43 @@ class logger
{
public:
typedef std::shared_ptr<sinks::base_sink> sink_ptr_t;
typedef std::vector<sink_ptr_t> sinks_vector_t;
using sink_ptr = std::shared_ptr<sinks::base_sink>;
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),
_formatter(new formatters::default_formatter()),
_sinks(),
_mutex() {
_formatter(f),
_sinks(sinks_list) {
//Seems that vs2013 doesnt support atomic member initialization in ctor, so its done here
_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;
//Non copybale in anyway
logger(const logger&) = delete;
logger(logger&&) = delete;
logger& operator=(const logger&) = delete;
logger& operator=(logger&&) = delete;
void set_name(const std::string& name);
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);
void set_level(c11log::level::level_enum);
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 info();
details::line_logger warn();
@ -63,9 +75,8 @@ private:
friend details::line_logger;
std::string _logger_name = "";
std::unique_ptr<c11log::formatters::formatter> _formatter;
formatter_ptr _formatter;
sinks_vector_t _sinks;
std::mutex _mutex;
std::atomic_int _atomic_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);
}
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;
}
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)
{
@ -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
{
{
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)
{
std::lock_guard<std::mutex> lock(_mutex);
for (auto &sink : _sinks)
sink->log(msg, level);
}
// Static factory function
inline c11log::logger& c11log::get_logger(const std::string& 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);
~async_sink();
void add_sink(logger::sink_ptr_t sink);
void remove_sink(logger::sink_ptr_t sink_ptr);
void add_sink(logger::sink_ptr sink);
void remove_sink(logger::sink_ptr sink_ptr);
//Wait to remaining items (if any) in the queue to be written and shutdown
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);
}
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());
}

View File

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