mirror of
https://github.com/gabime/spdlog.git
synced 2024-12-25 18:11:33 +08:00
logger refactoring to init lists and mutex remove
This commit is contained in:
parent
0caa2dd1e8
commit
a6d1ea77ee
@ -9,62 +9,37 @@
|
|||||||
|
|
||||||
#include "utils.h"
|
#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 std::cout;
|
||||||
using utils::format;
|
using std::endl;
|
||||||
|
using namespace std::chrono;
|
||||||
log_count = 0;
|
using namespace c11log;
|
||||||
std::this_thread::sleep_for(seconds(1));
|
using namespace utils;
|
||||||
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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
logger cout_logger (
|
||||||
|
"cout",
|
||||||
|
{null_sink, sinks::stdout_sink(), fsink});
|
||||||
|
|
||||||
auto &cout_logger = get_logger("cout");
|
|
||||||
cout_logger.add_sink(sinks::stdout_sink());
|
|
||||||
cout_logger.info() << "Hello cout logger!";
|
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;
|
||||||
|
@ -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];
|
||||||
|
@ -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>;
|
||||||
|
void add_logger(const std::string& name, logger_ptr);
|
||||||
logger_ptr get_logger(const std::string &name);
|
logger_ptr get_logger(const std::string &name);
|
||||||
static c11log::details::factory& instance();
|
static c11log::details::factory& instance();
|
||||||
private:
|
private:
|
||||||
logger_map _loggers;
|
|
||||||
std::mutex _loggers_mutex;
|
std::mutex _loggers_mutex;
|
||||||
|
logger_map _loggers;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
@ -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) {
|
||||||
|
if(enabled) {
|
||||||
callback_logger->_formatter->format_header(callback_logger->_logger_name,
|
callback_logger->_formatter->format_header(callback_logger->_logger_name,
|
||||||
msg_level,
|
msg_level,
|
||||||
log_clock::now(),
|
log_clock::now(),
|
||||||
_oss);
|
_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;
|
||||||
|
@ -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);
|
||||||
|
if(!logger_name.empty())
|
||||||
dest << " [" << logger_name << ":" << c11log::level::to_str(level) << "] ";
|
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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user