mirror of
https://github.com/gabime/spdlog.git
synced 2025-01-23 22:22:05 +08:00
astyle
This commit is contained in:
parent
58308df33c
commit
d163b8c45a
@ -1,5 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
find . -name "*\.h" -o -name "*\.cpp"|xargs dos2unix
|
find . -name "*\.h" -o -name "*\.cpp"|xargs dos2unix
|
||||||
find . -name "*\.h" -o -name "*\.cpp"|xargs astyle -n -A1
|
find . -name "*\.h" -o -name "*\.cpp"|xargs astyle -n -c -t4 -A1
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,17 +18,17 @@ namespace keywords = boost::log::keywords;
|
|||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
logging::add_file_log
|
logging::add_file_log
|
||||||
(
|
(
|
||||||
keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
|
keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
|
||||||
keywords::auto_flush = false,
|
keywords::auto_flush = false,
|
||||||
keywords::format = "[%TimeStamp%]: %Message%"
|
keywords::format = "[%TimeStamp%]: %Message%"
|
||||||
);
|
);
|
||||||
|
|
||||||
logging::core::get()->set_filter
|
logging::core::get()->set_filter
|
||||||
(
|
(
|
||||||
logging::trivial::severity >= logging::trivial::info
|
logging::trivial::severity >= logging::trivial::info
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -37,43 +37,43 @@ using namespace std;
|
|||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
int thread_count = 10;
|
int thread_count = 10;
|
||||||
if(argc > 1)
|
if(argc > 1)
|
||||||
thread_count = atoi(argv[1]);
|
thread_count = atoi(argv[1]);
|
||||||
|
|
||||||
int howmany = 1000000;
|
int howmany = 1000000;
|
||||||
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
logging::add_common_attributes();
|
logging::add_common_attributes();
|
||||||
|
|
||||||
|
|
||||||
using namespace logging::trivial;
|
using namespace logging::trivial;
|
||||||
|
|
||||||
src::severity_logger_mt< severity_level > lg;
|
src::severity_logger_mt< severity_level > lg;
|
||||||
|
|
||||||
std::atomic<int > msg_counter {0};
|
std::atomic<int > msg_counter {0};
|
||||||
vector<thread> threads;
|
vector<thread> threads;
|
||||||
|
|
||||||
for (int t = 0; t < thread_count; ++t)
|
for (int t = 0; t < thread_count; ++t)
|
||||||
{
|
{
|
||||||
threads.push_back(std::thread([&]()
|
threads.push_back(std::thread([&]()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int counter = ++msg_counter;
|
int counter = ++msg_counter;
|
||||||
if (counter > howmany) break;
|
if (counter > howmany) break;
|
||||||
BOOST_LOG_SEV(lg, info) << "boost message #" << counter << ": This is some text for your pleasure";
|
BOOST_LOG_SEV(lg, info) << "boost message #" << counter << ": This is some text for your pleasure";
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(auto &t:threads)
|
for(auto &t:threads)
|
||||||
{
|
{
|
||||||
t.join();
|
t.join();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -15,30 +15,30 @@ namespace keywords = boost::log::keywords;
|
|||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
logging::add_file_log
|
logging::add_file_log
|
||||||
(
|
(
|
||||||
keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
|
keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
|
||||||
keywords::auto_flush = false,
|
keywords::auto_flush = false,
|
||||||
keywords::format = "[%TimeStamp%]: %Message%"
|
keywords::format = "[%TimeStamp%]: %Message%"
|
||||||
);
|
);
|
||||||
|
|
||||||
logging::core::get()->set_filter
|
logging::core::get()->set_filter
|
||||||
(
|
(
|
||||||
logging::trivial::severity >= logging::trivial::info
|
logging::trivial::severity >= logging::trivial::info
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* [])
|
int main(int argc, char* [])
|
||||||
{
|
{
|
||||||
int howmany = 1000000;
|
int howmany = 1000000;
|
||||||
init();
|
init();
|
||||||
logging::add_common_attributes();
|
logging::add_common_attributes();
|
||||||
|
|
||||||
using namespace logging::trivial;
|
using namespace logging::trivial;
|
||||||
src::severity_logger_mt< severity_level > lg;
|
src::severity_logger_mt< severity_level > lg;
|
||||||
for(int i = 0 ; i < howmany; ++i)
|
for(int i = 0 ; i < howmany; ++i)
|
||||||
BOOST_LOG_SEV(lg, info) << "boost message #" << i << ": This is some text for your pleasure";
|
BOOST_LOG_SEV(lg, info) << "boost message #" << i << ": This is some text for your pleasure";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -11,37 +11,37 @@ using namespace std;
|
|||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
int thread_count = 10;
|
int thread_count = 10;
|
||||||
if(argc > 1)
|
if(argc > 1)
|
||||||
thread_count = atoi(argv[1]);
|
thread_count = atoi(argv[1]);
|
||||||
|
|
||||||
int howmany = 1000000;
|
int howmany = 1000000;
|
||||||
|
|
||||||
// Load configuration from file
|
// Load configuration from file
|
||||||
el::Configurations conf("easyl.conf");
|
el::Configurations conf("easyl.conf");
|
||||||
el::Loggers::reconfigureLogger("default", conf);
|
el::Loggers::reconfigureLogger("default", conf);
|
||||||
|
|
||||||
std::atomic<int > msg_counter {0};
|
std::atomic<int > msg_counter {0};
|
||||||
vector<thread> threads;
|
vector<thread> threads;
|
||||||
|
|
||||||
for (int t = 0; t < thread_count; ++t)
|
for (int t = 0; t < thread_count; ++t)
|
||||||
{
|
{
|
||||||
threads.push_back(std::thread([&]()
|
threads.push_back(std::thread([&]()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int counter = ++msg_counter;
|
int counter = ++msg_counter;
|
||||||
if (counter > howmany) break;
|
if (counter > howmany) break;
|
||||||
LOG(INFO) << "easylog message #" << counter << ": This is some text for your pleasure";
|
LOG(INFO) << "easylog message #" << counter << ": This is some text for your pleasure";
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(auto &t:threads)
|
for(auto &t:threads)
|
||||||
{
|
{
|
||||||
t.join();
|
t.join();
|
||||||
};
|
};
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@ int main(int, char* [])
|
|||||||
int howmany = 1000000;
|
int howmany = 1000000;
|
||||||
|
|
||||||
// Load configuration from file
|
// Load configuration from file
|
||||||
el::Configurations conf("easyl.conf");
|
el::Configurations conf("easyl.conf");
|
||||||
el::Loggers::reconfigureLogger("default", conf);
|
el::Loggers::reconfigureLogger("default", conf);
|
||||||
|
|
||||||
for(int i = 0 ; i < howmany; ++i)
|
for(int i = 0 ; i < howmany; ++i)
|
||||||
LOG(INFO) << "easylog message #" << i << ": This is some text for your pleasure";
|
LOG(INFO) << "easylog message #" << i << ": This is some text for your pleasure";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -14,44 +14,44 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using clock=steady_clock;
|
using clock=steady_clock;
|
||||||
int thread_count = 10;
|
int thread_count = 10;
|
||||||
|
|
||||||
if(argc > 1)
|
if(argc > 1)
|
||||||
thread_count = atoi(argv[1]);
|
thread_count = atoi(argv[1]);
|
||||||
int howmany = 1000000;
|
int howmany = 1000000;
|
||||||
|
|
||||||
g2LogWorker g2log(argv[0], "logs");
|
g2LogWorker g2log(argv[0], "logs");
|
||||||
g2::initializeLogging(&g2log);
|
g2::initializeLogging(&g2log);
|
||||||
|
|
||||||
|
|
||||||
std::atomic<int > msg_counter {0};
|
std::atomic<int > msg_counter {0};
|
||||||
vector<thread> threads;
|
vector<thread> threads;
|
||||||
auto start = clock::now();
|
auto start = clock::now();
|
||||||
for (int t = 0; t < thread_count; ++t)
|
for (int t = 0; t < thread_count; ++t)
|
||||||
{
|
{
|
||||||
threads.push_back(std::thread([&]()
|
threads.push_back(std::thread([&]()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int counter = ++msg_counter;
|
int counter = ++msg_counter;
|
||||||
if (counter > howmany) break;
|
if (counter > howmany) break;
|
||||||
LOG(INFO) << "g2log message #" << counter << ": This is some text for your pleasure";
|
LOG(INFO) << "g2log message #" << counter << ": This is some text for your pleasure";
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(auto &t:threads)
|
for(auto &t:threads)
|
||||||
{
|
{
|
||||||
t.join();
|
t.join();
|
||||||
};
|
};
|
||||||
|
|
||||||
duration<float> delta = clock::now() - start;
|
duration<float> delta = clock::now() - start;
|
||||||
float deltaf = delta.count();
|
float deltaf = delta.count();
|
||||||
auto rate = howmany/deltaf;
|
auto rate = howmany/deltaf;
|
||||||
|
|
||||||
cout << "Total: " << howmany << std::endl;
|
cout << "Total: " << howmany << std::endl;
|
||||||
cout << "Threads: " << thread_count << std::endl;
|
cout << "Threads: " << thread_count << std::endl;
|
||||||
std::cout << "Delta = " << deltaf << " seconds" << std::endl;
|
std::cout << "Delta = " << deltaf << " seconds" << std::endl;
|
||||||
std::cout << "Rate = " << rate << "/sec" << std::endl;
|
std::cout << "Rate = " << rate << "/sec" << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -9,37 +9,37 @@ using namespace std;
|
|||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
int thread_count = 10;
|
int thread_count = 10;
|
||||||
if(argc > 1)
|
if(argc > 1)
|
||||||
thread_count = atoi(argv[1]);
|
thread_count = atoi(argv[1]);
|
||||||
|
|
||||||
int howmany = 1000000;
|
int howmany = 1000000;
|
||||||
|
|
||||||
FLAGS_logtostderr = 0;
|
FLAGS_logtostderr = 0;
|
||||||
FLAGS_log_dir = "logs";
|
FLAGS_log_dir = "logs";
|
||||||
google::InitGoogleLogging(argv[0]);
|
google::InitGoogleLogging(argv[0]);
|
||||||
|
|
||||||
std::atomic<int > msg_counter {0};
|
std::atomic<int > msg_counter {0};
|
||||||
vector<thread> threads;
|
vector<thread> threads;
|
||||||
|
|
||||||
for (int t = 0; t < thread_count; ++t)
|
for (int t = 0; t < thread_count; ++t)
|
||||||
{
|
{
|
||||||
threads.push_back(std::thread([&]()
|
threads.push_back(std::thread([&]()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int counter = ++msg_counter;
|
int counter = ++msg_counter;
|
||||||
if (counter > howmany) break;
|
if (counter > howmany) break;
|
||||||
LOG(INFO) << "glog message #" << counter << ": This is some text for your pleasure";
|
LOG(INFO) << "glog message #" << counter << ": This is some text for your pleasure";
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(auto &t:threads)
|
for(auto &t:threads)
|
||||||
{
|
{
|
||||||
t.join();
|
t.join();
|
||||||
};
|
};
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
int main(int, char* argv[])
|
int main(int, char* argv[])
|
||||||
{
|
{
|
||||||
int howmany = 1000000;
|
int howmany = 1000000;
|
||||||
|
|
||||||
|
|
||||||
FLAGS_logtostderr = 0;
|
FLAGS_logtostderr = 0;
|
||||||
FLAGS_log_dir = "logs";
|
FLAGS_log_dir = "logs";
|
||||||
google::InitGoogleLogging(argv[0]);
|
google::InitGoogleLogging(argv[0]);
|
||||||
for(int i = 0 ; i < howmany; ++i)
|
for(int i = 0 ; i < howmany; ++i)
|
||||||
LOG(INFO) << "glog message # " << i << ": This is some text for your pleasure";
|
LOG(INFO) << "glog message # " << i << ": This is some text for your pleasure";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -16,43 +16,43 @@ int main(int argc, char* argv[])
|
|||||||
using clock=steady_clock;
|
using clock=steady_clock;
|
||||||
namespace spd = spdlog;
|
namespace spd = spdlog;
|
||||||
|
|
||||||
int thread_count = 10;
|
int thread_count = 10;
|
||||||
if(argc > 1)
|
if(argc > 1)
|
||||||
thread_count = atoi(argv[1]);
|
thread_count = atoi(argv[1]);
|
||||||
int howmany = 1000000;
|
int howmany = 1000000;
|
||||||
|
|
||||||
spd::set_async_mode(1048576);
|
spd::set_async_mode(1048576);
|
||||||
auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "logs/spd-bench-async.txt", false);
|
auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "logs/spd-bench-async.txt", false);
|
||||||
logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
|
logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
|
||||||
|
|
||||||
|
|
||||||
std::atomic<int > msg_counter {0};
|
std::atomic<int > msg_counter {0};
|
||||||
vector<thread> threads;
|
vector<thread> threads;
|
||||||
auto start = clock::now();
|
auto start = clock::now();
|
||||||
for (int t = 0; t < thread_count; ++t)
|
for (int t = 0; t < thread_count; ++t)
|
||||||
{
|
{
|
||||||
threads.push_back(std::thread([&]()
|
threads.push_back(std::thread([&]()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int counter = ++msg_counter;
|
int counter = ++msg_counter;
|
||||||
if (counter > howmany) break;
|
if (counter > howmany) break;
|
||||||
logger->info() << "spdlog message #" << counter << ": This is some text for your pleasure";
|
logger->info() << "spdlog message #" << counter << ": This is some text for your pleasure";
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto &t:threads)
|
for(auto &t:threads)
|
||||||
{
|
{
|
||||||
t.join();
|
t.join();
|
||||||
};
|
};
|
||||||
|
|
||||||
duration<float> delta = clock::now() - start;
|
duration<float> delta = clock::now() - start;
|
||||||
float deltaf = delta.count();
|
float deltaf = delta.count();
|
||||||
auto rate = howmany/deltaf;
|
auto rate = howmany/deltaf;
|
||||||
|
|
||||||
cout << "Total: " << howmany << std::endl;
|
cout << "Total: " << howmany << std::endl;
|
||||||
cout << "Threads: " << thread_count << std::endl;
|
cout << "Threads: " << thread_count << std::endl;
|
||||||
std::cout << "Delta = " << deltaf << " seconds" << std::endl;
|
std::cout << "Delta = " << deltaf << " seconds" << std::endl;
|
||||||
std::cout << "Rate = " << rate << "/sec" << std::endl;
|
std::cout << "Rate = " << rate << "/sec" << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -10,41 +10,41 @@ using namespace std;
|
|||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
int thread_count = 10;
|
int thread_count = 10;
|
||||||
if(argc > 1)
|
if(argc > 1)
|
||||||
thread_count = atoi(argv[1]);
|
thread_count = atoi(argv[1]);
|
||||||
|
|
||||||
int howmany = 1000000;
|
int howmany = 1000000;
|
||||||
|
|
||||||
namespace spd = spdlog;
|
namespace spd = spdlog;
|
||||||
|
|
||||||
auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "logs/spd-bench-mt.txt", false);
|
auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "logs/spd-bench-mt.txt", false);
|
||||||
|
|
||||||
logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
|
logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
|
||||||
|
|
||||||
std::atomic<int > msg_counter {0};
|
std::atomic<int > msg_counter {0};
|
||||||
vector<thread> threads;
|
vector<thread> threads;
|
||||||
|
|
||||||
for (int t = 0; t < thread_count; ++t)
|
for (int t = 0; t < thread_count; ++t)
|
||||||
{
|
{
|
||||||
threads.push_back(std::thread([&]()
|
threads.push_back(std::thread([&]()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int counter = ++msg_counter;
|
int counter = ++msg_counter;
|
||||||
if (counter > howmany) break;
|
if (counter > howmany) break;
|
||||||
logger->info() << "spdlog message #" << counter << ": This is some text for your pleasure";
|
logger->info() << "spdlog message #" << counter << ": This is some text for your pleasure";
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(auto &t:threads)
|
for(auto &t:threads)
|
||||||
{
|
{
|
||||||
t.join();
|
t.join();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
int main(int, char* [])
|
int main(int, char* [])
|
||||||
{
|
{
|
||||||
int howmany = 1000000;
|
int howmany = 1000000;
|
||||||
namespace spd = spdlog;
|
namespace spd = spdlog;
|
||||||
///Create a file rotating logger with 5mb size max and 3 rotated files
|
///Create a file rotating logger with 5mb size max and 3 rotated files
|
||||||
auto logger = spdlog::create<spd::sinks::simple_file_sink_st>("file_logger", "logs/spd-bench-st.txt", false);
|
auto logger = spdlog::create<spd::sinks::simple_file_sink_st>("file_logger", "logs/spd-bench-st.txt", false);
|
||||||
|
|
||||||
logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
|
logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
|
||||||
for(int i = 0 ; i < howmany; ++i)
|
for(int i = 0 ; i < howmany; ++i)
|
||||||
logger->info() << "spdlog message #" << i << ": This is some text for your pleasure";
|
logger->info() << "spdlog message #" << i << ": This is some text for your pleasure";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -50,110 +50,110 @@ void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count
|
|||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
int howmany = 1048576;
|
int howmany = 1048576;
|
||||||
int threads = 10;
|
int threads = 10;
|
||||||
bool auto_flush = false;
|
bool auto_flush = false;
|
||||||
int file_size = 30 * 1024 * 1024;
|
int file_size = 30 * 1024 * 1024;
|
||||||
int rotating_files = 5;
|
int rotating_files = 5;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
if(argc > 1)
|
if(argc > 1)
|
||||||
howmany = atoi(argv[1]);
|
howmany = atoi(argv[1]);
|
||||||
if (argc > 2)
|
if (argc > 2)
|
||||||
threads = atoi(argv[2]);
|
threads = atoi(argv[2]);
|
||||||
|
|
||||||
|
|
||||||
cout << "*******************************************************************************\n";
|
cout << "*******************************************************************************\n";
|
||||||
cout << "Single thread, " << format(howmany) << " iterations, auto flush=" << auto_flush << endl;
|
cout << "Single thread, " << format(howmany) << " iterations, auto flush=" << auto_flush << endl;
|
||||||
cout << "*******************************************************************************\n";
|
cout << "*******************************************************************************\n";
|
||||||
|
|
||||||
auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st", file_size, rotating_files, auto_flush);
|
auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st", file_size, rotating_files, auto_flush);
|
||||||
bench(howmany, rotating_st);
|
bench(howmany, rotating_st);
|
||||||
auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st", auto_flush);
|
auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st", auto_flush);
|
||||||
bench(howmany, daily_st);
|
bench(howmany, daily_st);
|
||||||
bench(howmany, spdlog::create<null_sink_st>("null_st"));
|
bench(howmany, spdlog::create<null_sink_st>("null_st"));
|
||||||
|
|
||||||
cout << "\n*******************************************************************************\n";
|
cout << "\n*******************************************************************************\n";
|
||||||
cout << threads << " threads sharing same logger, " << format(howmany) << " iterations, auto_flush=" << auto_flush << endl;
|
cout << threads << " threads sharing same logger, " << format(howmany) << " iterations, auto_flush=" << auto_flush << endl;
|
||||||
cout << "*******************************************************************************\n";
|
cout << "*******************************************************************************\n";
|
||||||
|
|
||||||
auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt", file_size, rotating_files, auto_flush);
|
auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt", file_size, rotating_files, auto_flush);
|
||||||
bench_mt(howmany, rotating_mt, threads);
|
bench_mt(howmany, rotating_mt, threads);
|
||||||
|
|
||||||
|
|
||||||
auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt", auto_flush);
|
auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt", auto_flush);
|
||||||
bench_mt(howmany, daily_mt, threads);
|
bench_mt(howmany, daily_mt, threads);
|
||||||
bench(howmany, spdlog::create<null_sink_st>("null_mt"));
|
bench(howmany, spdlog::create<null_sink_st>("null_mt"));
|
||||||
|
|
||||||
cout << "\n*******************************************************************************\n";
|
cout << "\n*******************************************************************************\n";
|
||||||
cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations, auto_flush=" << auto_flush << endl;
|
cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations, auto_flush=" << auto_flush << endl;
|
||||||
cout << "*******************************************************************************\n";
|
cout << "*******************************************************************************\n";
|
||||||
|
|
||||||
|
|
||||||
spdlog::set_async_mode(howmany);
|
spdlog::set_async_mode(howmany);
|
||||||
|
|
||||||
for(int i = 0; i < 3; ++i)
|
for(int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
auto as = spdlog::daily_logger_st("as", "logs/daily_async", auto_flush);
|
auto as = spdlog::daily_logger_st("as", "logs/daily_async", auto_flush);
|
||||||
bench_mt(howmany, as, threads);
|
bench_mt(howmany, as, threads);
|
||||||
spdlog::drop("as");
|
spdlog::drop("as");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception &ex)
|
catch (std::exception &ex)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: " << ex.what() << std::endl;
|
std::cerr << "Error: " << ex.what() << std::endl;
|
||||||
perror("Last error");
|
perror("Last error");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void bench(int howmany, std::shared_ptr<spdlog::logger> log)
|
void bench(int howmany, std::shared_ptr<spdlog::logger> log)
|
||||||
{
|
{
|
||||||
cout << log->name() << "...\t\t" << flush;
|
cout << log->name() << "...\t\t" << flush;
|
||||||
auto start = system_clock::now();
|
auto start = system_clock::now();
|
||||||
for (auto i = 0; i < howmany; ++i)
|
for (auto i = 0; i < howmany; ++i)
|
||||||
{
|
{
|
||||||
log->info("Hello logger: msg number {}", i);
|
log->info("Hello logger: msg number {}", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto delta = system_clock::now() - start;
|
auto delta = system_clock::now() - start;
|
||||||
auto delta_d = duration_cast<duration<double>> (delta).count();
|
auto delta_d = duration_cast<duration<double>> (delta).count();
|
||||||
cout << format(int(howmany / delta_d)) << "/sec" << endl;
|
cout << format(int(howmany / delta_d)) << "/sec" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
|
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
|
||||||
{
|
{
|
||||||
|
|
||||||
cout << log->name() << "...\t\t" << flush;
|
cout << log->name() << "...\t\t" << flush;
|
||||||
std::atomic<int > msg_counter {0};
|
std::atomic<int > msg_counter {0};
|
||||||
vector<thread> threads;
|
vector<thread> threads;
|
||||||
auto start = system_clock::now();
|
auto start = system_clock::now();
|
||||||
for (int t = 0; t < thread_count; ++t)
|
for (int t = 0; t < thread_count; ++t)
|
||||||
{
|
{
|
||||||
threads.push_back(std::thread([&]()
|
threads.push_back(std::thread([&]()
|
||||||
{
|
{
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
int counter = ++msg_counter;
|
int counter = ++msg_counter;
|
||||||
if (counter > howmany) break;
|
if (counter > howmany) break;
|
||||||
log->info("Hello logger: msg number {}", counter);
|
log->info("Hello logger: msg number {}", counter);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(auto &t:threads)
|
for(auto &t:threads)
|
||||||
{
|
{
|
||||||
t.join();
|
t.join();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
auto delta = system_clock::now() - start;
|
auto delta = system_clock::now() - start;
|
||||||
auto delta_d = duration_cast<duration<double>> (delta).count();
|
auto delta_d = duration_cast<duration<double>> (delta).count();
|
||||||
cout << format(int(howmany / delta_d)) << "/sec" << endl;
|
cout << format(int(howmany / delta_d)) << "/sec" << endl;
|
||||||
}
|
}
|
||||||
|
@ -30,61 +30,61 @@
|
|||||||
|
|
||||||
int main(int, char* [])
|
int main(int, char* [])
|
||||||
{
|
{
|
||||||
namespace spd = spdlog;
|
namespace spd = spdlog;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Set log level to all loggers to debug and above
|
// Set log level to all loggers to debug and above
|
||||||
spd::set_level(spd::level::debug);
|
spd::set_level(spd::level::debug);
|
||||||
|
|
||||||
// Create console, multithreaded logger
|
// Create console, multithreaded logger
|
||||||
auto console = spd::stdout_logger_mt("console");
|
auto console = spd::stdout_logger_mt("console");
|
||||||
console->info("Welcome to spdlog!") ;
|
console->info("Welcome to spdlog!") ;
|
||||||
console->info("An info message example {}..", 1);
|
console->info("An info message example {}..", 1);
|
||||||
console->info() << "Streams are supported too " << 1;
|
console->info() << "Streams are supported too " << 1;
|
||||||
|
|
||||||
console->info("Easy padding in numbers like {:08d}", 12);
|
console->info("Easy padding in numbers like {:08d}", 12);
|
||||||
console->info("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
|
console->info("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
|
||||||
console->info("Support for floats {:03.2f}", 1.23456);
|
console->info("Support for floats {:03.2f}", 1.23456);
|
||||||
console->info("Positional args are {1} {0}..", "too", "supported");
|
console->info("Positional args are {1} {0}..", "too", "supported");
|
||||||
|
|
||||||
console->info("{:<30}", "left aligned");
|
console->info("{:<30}", "left aligned");
|
||||||
console->info("{:>30}", "right aligned");
|
console->info("{:>30}", "right aligned");
|
||||||
console->info("{:^30}", "centered");
|
console->info("{:^30}", "centered");
|
||||||
|
|
||||||
// Create a file rotating logger with 5mb size max and 3 rotated files
|
// Create a file rotating logger with 5mb size max and 3 rotated files
|
||||||
auto file_logger = spd::rotating_logger_mt("file_logger", "logs/mylogfile", 1048576 * 5, 3);
|
auto file_logger = spd::rotating_logger_mt("file_logger", "logs/mylogfile", 1048576 * 5, 3);
|
||||||
file_logger->set_level(spd::level::info);
|
file_logger->set_level(spd::level::info);
|
||||||
for(int i = 0; i < 10; ++i)
|
for(int i = 0; i < 10; ++i)
|
||||||
file_logger->info("{} * {} equals {:>10}", i, i, i*i);
|
file_logger->info("{} * {} equals {:>10}", i, i, i*i);
|
||||||
|
|
||||||
// Customize msg format for all messages
|
// Customize msg format for all messages
|
||||||
spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
|
spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
|
||||||
file_logger->info("This is another message with custom format");
|
file_logger->info("This is another message with custom format");
|
||||||
|
|
||||||
spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
|
spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
|
||||||
|
|
||||||
SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
|
SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
|
||||||
SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
|
SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Asynchronous logging is very fast..
|
// Asynchronous logging is very fast..
|
||||||
// Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
|
// Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
|
||||||
//
|
//
|
||||||
size_t q_size = 1048576; //queue size must be power of 2
|
size_t q_size = 1048576; //queue size must be power of 2
|
||||||
spdlog::set_async_mode(q_size);
|
spdlog::set_async_mode(q_size);
|
||||||
auto async_file= spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
|
auto async_file= spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
|
||||||
async_file->info() << "This is async log.." << "Should be very fast!";
|
async_file->info() << "This is async log.." << "Should be very fast!";
|
||||||
|
|
||||||
// syslog example. linux only..
|
// syslog example. linux only..
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
std::string ident = "spdlog-example";
|
std::string ident = "spdlog-example";
|
||||||
auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID);
|
auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID);
|
||||||
syslog_logger->warn("This is warning that will end up in syslog. This is Linux only!");
|
syslog_logger->warn("This is warning that will end up in syslog. This is Linux only!");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (const spd::spdlog_ex& ex)
|
catch (const spd::spdlog_ex& ex)
|
||||||
{
|
{
|
||||||
std::cout << "Log failed: " << ex.what() << std::endl;
|
std::cout << "Log failed: " << ex.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,21 +34,21 @@ namespace utils
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::string format(const T& value)
|
inline std::string format(const T& value)
|
||||||
{
|
{
|
||||||
static std::locale loc("");
|
static std::locale loc("");
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss.imbue(loc);
|
ss.imbue(loc);
|
||||||
ss << value;
|
ss << value;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline std::string format(const double & value)
|
inline std::string format(const double & value)
|
||||||
{
|
{
|
||||||
static std::locale loc("");
|
static std::locale loc("");
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss.imbue(loc);
|
ss.imbue(loc);
|
||||||
ss << std::fixed << std::setprecision(1) << value;
|
ss << std::fixed << std::setprecision(1) << value;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,20 +50,20 @@ class async_log_helper;
|
|||||||
class async_logger :public logger
|
class async_logger :public logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<class It>
|
template<class It>
|
||||||
async_logger(const std::string& name, const It& begin, const It& end, size_t queue_size);
|
async_logger(const std::string& name, const It& begin, const It& end, size_t queue_size);
|
||||||
async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size);
|
async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size);
|
||||||
async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size);
|
async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _log_msg(details::log_msg& msg) override;
|
void _log_msg(details::log_msg& msg) override;
|
||||||
void _set_formatter(spdlog::formatter_ptr msg_formatter) override;
|
void _set_formatter(spdlog::formatter_ptr msg_formatter) override;
|
||||||
void _set_pattern(const std::string& pattern) override;
|
void _set_pattern(const std::string& pattern) override;
|
||||||
void _stop() override;
|
void _stop() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<details::async_log_helper> _async_log_helper;
|
std::unique_ptr<details::async_log_helper> _async_log_helper;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,8 @@ namespace spdlog
|
|||||||
|
|
||||||
class formatter;
|
class formatter;
|
||||||
|
|
||||||
namespace sinks {
|
namespace sinks
|
||||||
|
{
|
||||||
class sink;
|
class sink;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ static const char* level_names[] { "trace", "debug", "info", "notice", "warning"
|
|||||||
|
|
||||||
inline const char* to_str(spdlog::level::level_enum l)
|
inline const char* to_str(spdlog::level::level_enum l)
|
||||||
{
|
{
|
||||||
return level_names[l];
|
return level_names[l];
|
||||||
}
|
}
|
||||||
} //level
|
} //level
|
||||||
|
|
||||||
@ -80,13 +81,13 @@ inline const char* to_str(spdlog::level::level_enum l)
|
|||||||
class spdlog_ex : public std::exception
|
class spdlog_ex : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
spdlog_ex(const std::string& msg) :_msg(msg) {}
|
spdlog_ex(const std::string& msg) :_msg(msg) {}
|
||||||
const char* what() const SPDLOG_NOEXCEPT override
|
const char* what() const SPDLOG_NOEXCEPT override
|
||||||
{
|
{
|
||||||
return _msg.c_str();
|
return _msg.c_str();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::string _msg;
|
std::string _msg;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,93 +52,93 @@ namespace details
|
|||||||
|
|
||||||
class async_log_helper
|
class async_log_helper
|
||||||
{
|
{
|
||||||
// Async msg to move to/from the queue
|
// Async msg to move to/from the queue
|
||||||
// Movable only. should never be copied
|
// Movable only. should never be copied
|
||||||
struct async_msg
|
struct async_msg
|
||||||
{
|
{
|
||||||
std::string logger_name;
|
std::string logger_name;
|
||||||
level::level_enum level;
|
level::level_enum level;
|
||||||
log_clock::time_point time;
|
log_clock::time_point time;
|
||||||
std::string txt;
|
std::string txt;
|
||||||
|
|
||||||
async_msg() = default;
|
async_msg() = default;
|
||||||
~async_msg() = default;
|
~async_msg() = default;
|
||||||
|
|
||||||
async_msg(const async_msg&) = delete;
|
async_msg(const async_msg&) = delete;
|
||||||
async_msg& operator=(async_msg& other) = delete;
|
async_msg& operator=(async_msg& other) = delete;
|
||||||
|
|
||||||
async_msg(const details::log_msg& m) :
|
async_msg(const details::log_msg& m) :
|
||||||
logger_name(m.logger_name),
|
logger_name(m.logger_name),
|
||||||
level(m.level),
|
level(m.level),
|
||||||
time(m.time),
|
time(m.time),
|
||||||
txt(m.raw.data(), m.raw.size())
|
txt(m.raw.data(), m.raw.size())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
async_msg(async_msg&& other) :
|
async_msg(async_msg&& other) :
|
||||||
logger_name(std::move(other.logger_name)),
|
logger_name(std::move(other.logger_name)),
|
||||||
level(std::move(other.level)),
|
level(std::move(other.level)),
|
||||||
time(std::move(other.time)),
|
time(std::move(other.time)),
|
||||||
txt(std::move(other.txt))
|
txt(std::move(other.txt))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
async_msg& operator=(async_msg&& other)
|
async_msg& operator=(async_msg&& other)
|
||||||
{
|
{
|
||||||
logger_name = std::move(other.logger_name);
|
logger_name = std::move(other.logger_name);
|
||||||
level = other.level;
|
level = other.level;
|
||||||
time = std::move(other.time);
|
time = std::move(other.time);
|
||||||
txt = std::move(other.txt);
|
txt = std::move(other.txt);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void fill_log_msg(log_msg &msg)
|
void fill_log_msg(log_msg &msg)
|
||||||
{
|
{
|
||||||
msg.clear();
|
msg.clear();
|
||||||
msg.logger_name = logger_name;
|
msg.logger_name = logger_name;
|
||||||
msg.level = level;
|
msg.level = level;
|
||||||
msg.time = time;
|
msg.time = time;
|
||||||
msg.raw << txt;
|
msg.raw << txt;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using item_type = async_msg;
|
using item_type = async_msg;
|
||||||
using q_type = details::mpmc_bounded_queue<item_type>;
|
using q_type = details::mpmc_bounded_queue<item_type>;
|
||||||
|
|
||||||
using clock = std::chrono::steady_clock;
|
using clock = std::chrono::steady_clock;
|
||||||
|
|
||||||
|
|
||||||
async_log_helper(formatter_ptr formatter, const std::vector<sink_ptr>& sinks, size_t queue_size);
|
async_log_helper(formatter_ptr formatter, const std::vector<sink_ptr>& sinks, size_t queue_size);
|
||||||
void log(const details::log_msg& msg);
|
void log(const details::log_msg& msg);
|
||||||
|
|
||||||
//Stop logging and join the back thread
|
//Stop logging and join the back thread
|
||||||
~async_log_helper();
|
~async_log_helper();
|
||||||
void set_formatter(formatter_ptr);
|
void set_formatter(formatter_ptr);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
formatter_ptr _formatter;
|
formatter_ptr _formatter;
|
||||||
std::vector<std::shared_ptr<sinks::sink>> _sinks;
|
std::vector<std::shared_ptr<sinks::sink>> _sinks;
|
||||||
q_type _q;
|
q_type _q;
|
||||||
std::thread _worker_thread;
|
std::thread _worker_thread;
|
||||||
|
|
||||||
// last exception thrown from the worker thread
|
// last exception thrown from the worker thread
|
||||||
std::shared_ptr<spdlog_ex> _last_workerthread_ex;
|
std::shared_ptr<spdlog_ex> _last_workerthread_ex;
|
||||||
|
|
||||||
|
|
||||||
// throw last worker thread exception or if worker thread is not active
|
// throw last worker thread exception or if worker thread is not active
|
||||||
void throw_if_bad_worker();
|
void throw_if_bad_worker();
|
||||||
|
|
||||||
// worker thread main loop
|
// worker thread main loop
|
||||||
void worker_loop();
|
void worker_loop();
|
||||||
|
|
||||||
//pop next message from the queue and process it
|
//pop next message from the queue and process it
|
||||||
//return true if a message was available (queue was not empty), will set the last_pop to the pop time
|
//return true if a message was available (queue was not empty), will set the last_pop to the pop time
|
||||||
bool process_next_msg(clock::time_point& last_pop);
|
bool process_next_msg(clock::time_point& last_pop);
|
||||||
|
|
||||||
// guess how much to sleep if queue is empty/full using last succesful op time as hint
|
// guess how much to sleep if queue is empty/full using last succesful op time as hint
|
||||||
static void sleep_or_yield(const clock::time_point& last_op_time);
|
static void sleep_or_yield(const clock::time_point& last_op_time);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -148,10 +148,10 @@ private:
|
|||||||
// async_sink class implementation
|
// async_sink class implementation
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
inline spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatter, const std::vector<sink_ptr>& sinks, size_t queue_size):
|
inline spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatter, const std::vector<sink_ptr>& sinks, size_t queue_size):
|
||||||
_formatter(formatter),
|
_formatter(formatter),
|
||||||
_sinks(sinks),
|
_sinks(sinks),
|
||||||
_q(queue_size),
|
_q(queue_size),
|
||||||
_worker_thread(&async_log_helper::worker_loop, this)
|
_worker_thread(&async_log_helper::worker_loop, this)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Send to the worker thread termination message(level=off)
|
// Send to the worker thread termination message(level=off)
|
||||||
@ -159,30 +159,30 @@ inline spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatt
|
|||||||
inline spdlog::details::async_log_helper::~async_log_helper()
|
inline spdlog::details::async_log_helper::~async_log_helper()
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
log(log_msg(level::off));
|
log(log_msg(level::off));
|
||||||
_worker_thread.join();
|
_worker_thread.join();
|
||||||
}
|
}
|
||||||
catch (...) //Dont crash if thread not joinable
|
catch (...) //Dont crash if thread not joinable
|
||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Try to push and block until succeeded
|
//Try to push and block until succeeded
|
||||||
inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
|
inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
|
||||||
{
|
{
|
||||||
throw_if_bad_worker();
|
throw_if_bad_worker();
|
||||||
async_msg new_msg(msg);
|
async_msg new_msg(msg);
|
||||||
if (!_q.enqueue(std::move(new_msg)))
|
if (!_q.enqueue(std::move(new_msg)))
|
||||||
{
|
{
|
||||||
auto last_op_time = clock::now();
|
auto last_op_time = clock::now();
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
sleep_or_yield(last_op_time);
|
sleep_or_yield(last_op_time);
|
||||||
}
|
}
|
||||||
while (!_q.enqueue(std::move(new_msg)));
|
while (!_q.enqueue(std::move(new_msg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,15 +192,15 @@ inline void spdlog::details::async_log_helper::worker_loop()
|
|||||||
{
|
{
|
||||||
clock::time_point last_pop = clock::now();
|
clock::time_point last_pop = clock::now();
|
||||||
while(process_next_msg(last_pop));
|
while(process_next_msg(last_pop));
|
||||||
}
|
}
|
||||||
catch (const std::exception& ex)
|
catch (const std::exception& ex)
|
||||||
{
|
{
|
||||||
_last_workerthread_ex = std::make_shared<spdlog_ex>(std::string("async_logger worker thread exception: ") + ex.what());
|
_last_workerthread_ex = std::make_shared<spdlog_ex>(std::string("async_logger worker thread exception: ") + ex.what());
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
_last_workerthread_ex = std::make_shared<spdlog_ex>("async_logger worker thread exception");
|
_last_workerthread_ex = std::make_shared<spdlog_ex>("async_logger worker thread exception");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process next message in the queue
|
// Process next message in the queue
|
||||||
@ -208,66 +208,66 @@ inline void spdlog::details::async_log_helper::worker_loop()
|
|||||||
inline bool spdlog::details::async_log_helper::process_next_msg(clock::time_point& last_pop)
|
inline bool spdlog::details::async_log_helper::process_next_msg(clock::time_point& last_pop)
|
||||||
{
|
{
|
||||||
|
|
||||||
async_msg incoming_async_msg;
|
async_msg incoming_async_msg;
|
||||||
log_msg incoming_log_msg;
|
log_msg incoming_log_msg;
|
||||||
|
|
||||||
if (_q.dequeue(incoming_async_msg))
|
if (_q.dequeue(incoming_async_msg))
|
||||||
{
|
{
|
||||||
last_pop = clock::now();
|
last_pop = clock::now();
|
||||||
|
|
||||||
if(incoming_async_msg.level == level::off)
|
if(incoming_async_msg.level == level::off)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
incoming_async_msg.fill_log_msg(incoming_log_msg);
|
incoming_async_msg.fill_log_msg(incoming_log_msg);
|
||||||
_formatter->format(incoming_log_msg);
|
_formatter->format(incoming_log_msg);
|
||||||
for (auto &s : _sinks)
|
for (auto &s : _sinks)
|
||||||
s->log(incoming_log_msg);
|
s->log(incoming_log_msg);
|
||||||
}
|
}
|
||||||
else //empty queue
|
else //empty queue
|
||||||
{
|
{
|
||||||
sleep_or_yield(last_pop);
|
sleep_or_yield(last_pop);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter)
|
inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter)
|
||||||
{
|
{
|
||||||
_formatter = msg_formatter;
|
_formatter = msg_formatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Sleep,yield or return immediatly using the time passed since last message as a hint
|
// Sleep,yield or return immediatly using the time passed since last message as a hint
|
||||||
inline void spdlog::details::async_log_helper::sleep_or_yield(const clock::time_point& last_op_time)
|
inline void spdlog::details::async_log_helper::sleep_or_yield(const clock::time_point& last_op_time)
|
||||||
{
|
{
|
||||||
using std::chrono::milliseconds;
|
using std::chrono::milliseconds;
|
||||||
using namespace std::this_thread;
|
using namespace std::this_thread;
|
||||||
|
|
||||||
auto time_since_op = clock::now() - last_op_time;
|
auto time_since_op = clock::now() - last_op_time;
|
||||||
|
|
||||||
//spin upto 1 ms
|
//spin upto 1 ms
|
||||||
if (time_since_op <= milliseconds(1))
|
if (time_since_op <= milliseconds(1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// yield upto 10ms
|
// yield upto 10ms
|
||||||
if (time_since_op <= milliseconds(10))
|
if (time_since_op <= milliseconds(10))
|
||||||
return yield();
|
return yield();
|
||||||
|
|
||||||
|
|
||||||
// sleep for half of duration since last op
|
// sleep for half of duration since last op
|
||||||
if (time_since_op <= milliseconds(100))
|
if (time_since_op <= milliseconds(100))
|
||||||
return sleep_for(time_since_op / 2);
|
return sleep_for(time_since_op / 2);
|
||||||
|
|
||||||
return sleep_for(milliseconds(100));
|
return sleep_for(milliseconds(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
//throw if the worker thread threw an exception or not active
|
//throw if the worker thread threw an exception or not active
|
||||||
inline void spdlog::details::async_log_helper::throw_if_bad_worker()
|
inline void spdlog::details::async_log_helper::throw_if_bad_worker()
|
||||||
{
|
{
|
||||||
if (_last_workerthread_ex)
|
if (_last_workerthread_ex)
|
||||||
{
|
{
|
||||||
auto ex = std::move(_last_workerthread_ex);
|
auto ex = std::move(_last_workerthread_ex);
|
||||||
throw *ex;
|
throw *ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,38 +35,38 @@
|
|||||||
|
|
||||||
template<class It>
|
template<class It>
|
||||||
inline spdlog::async_logger::async_logger(const std::string& logger_name, const It& begin, const It& end, size_t queue_size) :
|
inline spdlog::async_logger::async_logger(const std::string& logger_name, const It& begin, const It& end, size_t queue_size) :
|
||||||
logger(logger_name, begin, end),
|
logger(logger_name, begin, end),
|
||||||
_async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size))
|
_async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::async_logger::async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size) :
|
inline spdlog::async_logger::async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size) :
|
||||||
async_logger(logger_name, sinks.begin(), sinks.end(), queue_size) {}
|
async_logger(logger_name, sinks.begin(), sinks.end(), queue_size) {}
|
||||||
|
|
||||||
inline spdlog::async_logger::async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size) :
|
inline spdlog::async_logger::async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size) :
|
||||||
async_logger(logger_name, { single_sink }, queue_size) {}
|
async_logger(logger_name, { single_sink }, queue_size) {}
|
||||||
|
|
||||||
|
|
||||||
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)
|
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)
|
||||||
{
|
{
|
||||||
_formatter = msg_formatter;
|
_formatter = msg_formatter;
|
||||||
_async_log_helper->set_formatter(_formatter);
|
_async_log_helper->set_formatter(_formatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::async_logger::_set_pattern(const std::string& pattern)
|
inline void spdlog::async_logger::_set_pattern(const std::string& pattern)
|
||||||
{
|
{
|
||||||
_formatter = std::make_shared<pattern_formatter>(pattern);
|
_formatter = std::make_shared<pattern_formatter>(pattern);
|
||||||
_async_log_helper->set_formatter(_formatter);
|
_async_log_helper->set_formatter(_formatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline void spdlog::async_logger::_stop()
|
inline void spdlog::async_logger::_stop()
|
||||||
{
|
{
|
||||||
set_level(level::off);
|
set_level(level::off);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::async_logger::_log_msg(details::log_msg& msg)
|
inline void spdlog::async_logger::_log_msg(details::log_msg& msg)
|
||||||
{
|
{
|
||||||
_async_log_helper->log(msg);
|
_async_log_helper->log(msg);
|
||||||
}
|
}
|
||||||
|
@ -45,93 +45,93 @@ namespace details
|
|||||||
class file_helper
|
class file_helper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const int open_tries = 5;
|
const int open_tries = 5;
|
||||||
const int open_interval = 10;
|
const int open_interval = 10;
|
||||||
|
|
||||||
explicit file_helper(bool auto_flush):
|
explicit file_helper(bool auto_flush):
|
||||||
_fd(nullptr),
|
_fd(nullptr),
|
||||||
_auto_flush(auto_flush)
|
_auto_flush(auto_flush)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
file_helper(const file_helper&) = delete;
|
file_helper(const file_helper&) = delete;
|
||||||
file_helper& operator=(const file_helper&) = delete;
|
file_helper& operator=(const file_helper&) = delete;
|
||||||
|
|
||||||
~file_helper()
|
~file_helper()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void open(const std::string& fname, bool truncate=false)
|
void open(const std::string& fname, bool truncate=false)
|
||||||
{
|
{
|
||||||
|
|
||||||
close();
|
close();
|
||||||
const char* mode = truncate ? "wb" : "ab";
|
const char* mode = truncate ? "wb" : "ab";
|
||||||
_filename = fname;
|
_filename = fname;
|
||||||
for (int tries = 0; tries < open_tries; ++tries)
|
for (int tries = 0; tries < open_tries; ++tries)
|
||||||
{
|
{
|
||||||
if(!os::fopen_s(&_fd, fname, mode))
|
if(!os::fopen_s(&_fd, fname, mode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(open_interval));
|
std::this_thread::sleep_for(std::chrono::milliseconds(open_interval));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw spdlog_ex("Failed opening file " + fname + " for writing");
|
throw spdlog_ex("Failed opening file " + fname + " for writing");
|
||||||
}
|
}
|
||||||
|
|
||||||
void reopen(bool truncate)
|
void reopen(bool truncate)
|
||||||
{
|
{
|
||||||
if(_filename.empty())
|
if(_filename.empty())
|
||||||
throw spdlog_ex("Failed re opening file - was not opened before");
|
throw spdlog_ex("Failed re opening file - was not opened before");
|
||||||
open(_filename, truncate);
|
open(_filename, truncate);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void close()
|
void close()
|
||||||
{
|
{
|
||||||
if (_fd)
|
if (_fd)
|
||||||
{
|
{
|
||||||
std::fclose(_fd);
|
std::fclose(_fd);
|
||||||
_fd = nullptr;
|
_fd = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const log_msg& msg)
|
void write(const log_msg& msg)
|
||||||
{
|
{
|
||||||
|
|
||||||
size_t size = msg.formatted.size();
|
size_t size = msg.formatted.size();
|
||||||
auto data = msg.formatted.data();
|
auto data = msg.formatted.data();
|
||||||
if(std::fwrite(data, 1, size, _fd) != size)
|
if(std::fwrite(data, 1, size, _fd) != size)
|
||||||
throw spdlog_ex("Failed writing to file " + _filename);
|
throw spdlog_ex("Failed writing to file " + _filename);
|
||||||
|
|
||||||
if(_auto_flush)
|
if(_auto_flush)
|
||||||
std::fflush(_fd);
|
std::fflush(_fd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& filename() const
|
const std::string& filename() const
|
||||||
{
|
{
|
||||||
return _filename;
|
return _filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool file_exists(const std::string& name)
|
static bool file_exists(const std::string& name)
|
||||||
{
|
{
|
||||||
FILE* file;
|
FILE* file;
|
||||||
if (!os::fopen_s(&file, name.c_str(), "r"))
|
if (!os::fopen_s(&file, name.c_str(), "r"))
|
||||||
{
|
{
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILE* _fd;
|
FILE* _fd;
|
||||||
std::string _filename;
|
std::string _filename;
|
||||||
bool _auto_flush;
|
bool _auto_flush;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -38,73 +38,73 @@ namespace details
|
|||||||
class line_logger
|
class line_logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled):
|
line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled):
|
||||||
_callback_logger(callback_logger),
|
_callback_logger(callback_logger),
|
||||||
_log_msg(msg_level),
|
_log_msg(msg_level),
|
||||||
_enabled(enabled)
|
_enabled(enabled)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// 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=(const line_logger&) = delete;
|
||||||
line_logger& operator=(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),
|
||||||
_log_msg(std::move(other._log_msg)),
|
_log_msg(std::move(other._log_msg)),
|
||||||
_enabled(other._enabled)
|
_enabled(other._enabled)
|
||||||
{
|
{
|
||||||
other.disable();
|
other.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Log the log message using the callback logger
|
//Log the log message using the callback logger
|
||||||
~line_logger()
|
~line_logger()
|
||||||
{
|
{
|
||||||
if (_enabled)
|
if (_enabled)
|
||||||
{
|
{
|
||||||
_log_msg.logger_name = _callback_logger->name();
|
_log_msg.logger_name = _callback_logger->name();
|
||||||
_log_msg.time = log_clock::now();
|
_log_msg.time = log_clock::now();
|
||||||
_callback_logger->_log_msg(_log_msg);
|
_callback_logger->_log_msg(_log_msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void write(const char* fmt, const Args&... args)
|
void write(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
if (!_enabled)
|
if (!_enabled)
|
||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_log_msg.raw.write(fmt, args...);
|
_log_msg.raw.write(fmt, args...);
|
||||||
}
|
}
|
||||||
catch (const fmt::FormatError& e)
|
catch (const fmt::FormatError& e)
|
||||||
{
|
{
|
||||||
throw spdlog_ex(fmt::format("formatting error while processing format string '{}': {}", fmt, e.what()));
|
throw spdlog_ex(fmt::format("formatting error while processing format string '{}': {}", fmt, e.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
line_logger& operator<<(const T& what)
|
line_logger& operator<<(const T& what)
|
||||||
{
|
{
|
||||||
if (_enabled)
|
if (_enabled)
|
||||||
_log_msg.raw << what;
|
_log_msg.raw << what;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void disable()
|
void disable()
|
||||||
{
|
{
|
||||||
_enabled = false;
|
_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
logger* _callback_logger;
|
logger* _callback_logger;
|
||||||
log_msg _log_msg;
|
log_msg _log_msg;
|
||||||
bool _enabled;
|
bool _enabled;
|
||||||
};
|
};
|
||||||
} //Namespace details
|
} //Namespace details
|
||||||
} // Namespace spdlog
|
} // Namespace spdlog
|
||||||
|
@ -33,63 +33,62 @@ namespace details
|
|||||||
{
|
{
|
||||||
struct log_msg
|
struct log_msg
|
||||||
{
|
{
|
||||||
log_msg() = default;
|
log_msg() = default;
|
||||||
log_msg(level::level_enum l):
|
log_msg(level::level_enum l):
|
||||||
logger_name(),
|
logger_name(),
|
||||||
level(l),
|
level(l),
|
||||||
time(),
|
time(),
|
||||||
raw(),
|
raw(),
|
||||||
formatted() {}
|
formatted() {}
|
||||||
|
|
||||||
|
|
||||||
log_msg(const log_msg& other) :
|
log_msg(const log_msg& other) :
|
||||||
logger_name(other.logger_name),
|
logger_name(other.logger_name),
|
||||||
level(other.level),
|
level(other.level),
|
||||||
time(other.time)
|
time(other.time)
|
||||||
{
|
{
|
||||||
if (other.raw.size())
|
if (other.raw.size())
|
||||||
raw << fmt::BasicStringRef<char>(other.raw.data(), other.raw.size());
|
raw << fmt::BasicStringRef<char>(other.raw.data(), other.raw.size());
|
||||||
if (other.formatted.size())
|
if (other.formatted.size())
|
||||||
formatted << fmt::BasicStringRef<char>(other.formatted.data(), other.formatted.size());
|
formatted << fmt::BasicStringRef<char>(other.formatted.data(), other.formatted.size());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
log_msg(log_msg&& other) :
|
||||||
|
logger_name(std::move(other.logger_name)),
|
||||||
|
level(other.level),
|
||||||
|
time(std::move(other.time)),
|
||||||
|
raw(std::move(other.raw)),
|
||||||
|
formatted(std::move(other.formatted))
|
||||||
|
{
|
||||||
|
other.clear();
|
||||||
|
}
|
||||||
|
|
||||||
log_msg(log_msg&& other) :
|
log_msg& operator=(log_msg&& other)
|
||||||
logger_name(std::move(other.logger_name)),
|
{
|
||||||
level(other.level),
|
if (this == &other)
|
||||||
time(std::move(other.time)),
|
return *this;
|
||||||
raw(std::move(other.raw)),
|
|
||||||
formatted(std::move(other.formatted))
|
|
||||||
{
|
|
||||||
other.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
log_msg& operator=(log_msg&& other)
|
logger_name = std::move(other.logger_name);
|
||||||
{
|
level = other.level;
|
||||||
if (this == &other)
|
time = std::move(other.time);
|
||||||
return *this;
|
raw = std::move(other.raw);
|
||||||
|
formatted = std::move(other.formatted);
|
||||||
|
other.clear();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
logger_name = std::move(other.logger_name);
|
void clear()
|
||||||
level = other.level;
|
{
|
||||||
time = std::move(other.time);
|
level = level::off;
|
||||||
raw = std::move(other.raw);
|
raw.clear();
|
||||||
formatted = std::move(other.formatted);
|
formatted.clear();
|
||||||
other.clear();
|
}
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
std::string logger_name;
|
||||||
{
|
level::level_enum level;
|
||||||
level = level::off;
|
log_clock::time_point time;
|
||||||
raw.clear();
|
fmt::MemoryWriter raw;
|
||||||
formatted.clear();
|
fmt::MemoryWriter formatted;
|
||||||
}
|
|
||||||
|
|
||||||
std::string logger_name;
|
|
||||||
level::level_enum level;
|
|
||||||
log_clock::time_point time;
|
|
||||||
fmt::MemoryWriter raw;
|
|
||||||
fmt::MemoryWriter formatted;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,23 +34,23 @@
|
|||||||
// all other ctors will call this one
|
// all other ctors will call this one
|
||||||
template<class It>
|
template<class It>
|
||||||
inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end) :
|
inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end) :
|
||||||
_name(logger_name),
|
_name(logger_name),
|
||||||
_sinks(begin, end),
|
_sinks(begin, end),
|
||||||
_formatter(std::make_shared<pattern_formatter>("%+"))
|
_formatter(std::make_shared<pattern_formatter>("%+"))
|
||||||
{
|
{
|
||||||
|
|
||||||
// no support under vs2013 for member initialization for std::atomic
|
// no support under vs2013 for member initialization for std::atomic
|
||||||
_level = level::info;
|
_level = level::info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ctor with sinks as init list
|
// ctor with sinks as init list
|
||||||
inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list) :
|
inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list) :
|
||||||
logger(logger_name, sinks_list.begin(), sinks_list.end()) {}
|
logger(logger_name, sinks_list.begin(), sinks_list.end()) {}
|
||||||
|
|
||||||
|
|
||||||
// ctor with single sink
|
// ctor with single sink
|
||||||
inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink) :
|
inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink) :
|
||||||
logger(logger_name, { single_sink }) {}
|
logger(logger_name, { single_sink }) {}
|
||||||
|
|
||||||
|
|
||||||
inline spdlog::logger::~logger() = default;
|
inline spdlog::logger::~logger() = default;
|
||||||
@ -58,12 +58,12 @@ inline spdlog::logger::~logger() = default;
|
|||||||
|
|
||||||
inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter)
|
inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter)
|
||||||
{
|
{
|
||||||
_set_formatter(msg_formatter);
|
_set_formatter(msg_formatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::logger::set_pattern(const std::string& pattern)
|
inline void spdlog::logger::set_pattern(const std::string& pattern)
|
||||||
{
|
{
|
||||||
_set_pattern(pattern);
|
_set_pattern(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -74,15 +74,15 @@ inline void spdlog::logger::set_pattern(const std::string& pattern)
|
|||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
bool msg_enabled = should_log(lvl);
|
bool msg_enabled = should_log(lvl);
|
||||||
details::line_logger l(this, lvl, msg_enabled);
|
details::line_logger l(this, lvl, msg_enabled);
|
||||||
l.write(fmt, args...);
|
l.write(fmt, args...);
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl)
|
inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl)
|
||||||
{
|
{
|
||||||
return details::line_logger(this, lvl, should_log(lvl));
|
return details::line_logger(this, lvl, should_log(lvl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -92,55 +92,55 @@ inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level
|
|||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::trace(const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::trace(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::trace, fmt, args...);
|
return _log_if_enabled(level::trace, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::debug(const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::debug(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::debug, fmt, args...);
|
return _log_if_enabled(level::debug, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::info(const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::info(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::info, fmt, args...);
|
return _log_if_enabled(level::info, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::notice(const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::notice(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::notice, fmt, args...);
|
return _log_if_enabled(level::notice, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::warn(const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::warn(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::warn, fmt, args...);
|
return _log_if_enabled(level::warn, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::error(const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::error(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::err, fmt, args...);
|
return _log_if_enabled(level::err, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::critical(const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::critical(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::critical, fmt, args...);
|
return _log_if_enabled(level::critical, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::alert(const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::alert(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::alert, fmt, args...);
|
return _log_if_enabled(level::alert, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::emerg(const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::emerg(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::emerg, fmt, args...);
|
return _log_if_enabled(level::emerg, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -152,48 +152,48 @@ inline spdlog::details::line_logger spdlog::logger::emerg(const char* fmt, const
|
|||||||
|
|
||||||
inline spdlog::details::line_logger spdlog::logger::trace()
|
inline spdlog::details::line_logger spdlog::logger::trace()
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::trace);
|
return _log_if_enabled(level::trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline spdlog::details::line_logger spdlog::logger::debug()
|
inline spdlog::details::line_logger spdlog::logger::debug()
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::debug);
|
return _log_if_enabled(level::debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger spdlog::logger::info()
|
inline spdlog::details::line_logger spdlog::logger::info()
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::info);
|
return _log_if_enabled(level::info);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger spdlog::logger::notice()
|
inline spdlog::details::line_logger spdlog::logger::notice()
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::notice);
|
return _log_if_enabled(level::notice);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger spdlog::logger::warn()
|
inline spdlog::details::line_logger spdlog::logger::warn()
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::warn);
|
return _log_if_enabled(level::warn);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger spdlog::logger::error()
|
inline spdlog::details::line_logger spdlog::logger::error()
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::err);
|
return _log_if_enabled(level::err);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger spdlog::logger::critical()
|
inline spdlog::details::line_logger spdlog::logger::critical()
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::critical);
|
return _log_if_enabled(level::critical);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger spdlog::logger::alert()
|
inline spdlog::details::line_logger spdlog::logger::alert()
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::alert);
|
return _log_if_enabled(level::alert);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger spdlog::logger::emerg()
|
inline spdlog::details::line_logger spdlog::logger::emerg()
|
||||||
{
|
{
|
||||||
return _log_if_enabled(level::emerg);
|
return _log_if_enabled(level::emerg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -201,9 +201,9 @@ inline spdlog::details::line_logger spdlog::logger::emerg()
|
|||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline spdlog::details::line_logger spdlog::logger::force_log(level::level_enum lvl, const char* fmt, const Args&... args)
|
inline spdlog::details::line_logger spdlog::logger::force_log(level::level_enum lvl, const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
details::line_logger l(this, lvl, true);
|
details::line_logger l(this, lvl, true);
|
||||||
l.write(fmt, args...);
|
l.write(fmt, args...);
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -211,27 +211,27 @@ inline spdlog::details::line_logger spdlog::logger::force_log(level::level_enum
|
|||||||
//
|
//
|
||||||
inline const std::string& spdlog::logger::name() const
|
inline const std::string& spdlog::logger::name() const
|
||||||
{
|
{
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
|
inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
|
||||||
{
|
{
|
||||||
_level.store(log_level);
|
_level.store(log_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::level::level_enum spdlog::logger::level() const
|
inline spdlog::level::level_enum spdlog::logger::level() const
|
||||||
{
|
{
|
||||||
return static_cast<spdlog::level::level_enum>(_level.load());
|
return static_cast<spdlog::level::level_enum>(_level.load());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const
|
inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const
|
||||||
{
|
{
|
||||||
return msg_level >= _level.load();
|
return msg_level >= _level.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::logger::stop()
|
inline void spdlog::logger::stop()
|
||||||
{
|
{
|
||||||
_stop();
|
_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -239,23 +239,23 @@ inline void spdlog::logger::stop()
|
|||||||
//
|
//
|
||||||
inline void spdlog::logger::_log_msg(details::log_msg& msg)
|
inline void spdlog::logger::_log_msg(details::log_msg& msg)
|
||||||
{
|
{
|
||||||
_formatter->format(msg);
|
_formatter->format(msg);
|
||||||
for (auto &sink : _sinks)
|
for (auto &sink : _sinks)
|
||||||
sink->log(msg);
|
sink->log(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::logger::_set_pattern(const std::string& pattern)
|
inline void spdlog::logger::_set_pattern(const std::string& pattern)
|
||||||
{
|
{
|
||||||
_formatter = std::make_shared<pattern_formatter>(pattern);
|
_formatter = std::make_shared<pattern_formatter>(pattern);
|
||||||
}
|
}
|
||||||
inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter)
|
inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter)
|
||||||
{
|
{
|
||||||
_formatter = msg_formatter;
|
_formatter = msg_formatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::logger::_stop()
|
inline void spdlog::logger::_stop()
|
||||||
{
|
{
|
||||||
set_level(level::off);
|
set_level(level::off);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,101 +74,101 @@ class mpmc_bounded_queue
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using item_type = T;
|
using item_type = T;
|
||||||
mpmc_bounded_queue(size_t buffer_size)
|
mpmc_bounded_queue(size_t buffer_size)
|
||||||
: buffer_(new cell_t [buffer_size]),
|
: buffer_(new cell_t [buffer_size]),
|
||||||
buffer_mask_(buffer_size - 1)
|
buffer_mask_(buffer_size - 1)
|
||||||
{
|
{
|
||||||
//queue size must be power of two
|
//queue size must be power of two
|
||||||
if(!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0)))
|
if(!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0)))
|
||||||
throw spdlog_ex("async logger queue size must be power of two");
|
throw spdlog_ex("async logger queue size must be power of two");
|
||||||
|
|
||||||
for (size_t i = 0; i != buffer_size; i += 1)
|
for (size_t i = 0; i != buffer_size; i += 1)
|
||||||
buffer_[i].sequence_.store(i, std::memory_order_relaxed);
|
buffer_[i].sequence_.store(i, std::memory_order_relaxed);
|
||||||
enqueue_pos_.store(0, std::memory_order_relaxed);
|
enqueue_pos_.store(0, std::memory_order_relaxed);
|
||||||
dequeue_pos_.store(0, std::memory_order_relaxed);
|
dequeue_pos_.store(0, std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
~mpmc_bounded_queue()
|
~mpmc_bounded_queue()
|
||||||
{
|
{
|
||||||
delete [] buffer_;
|
delete [] buffer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool enqueue(T&& data)
|
bool enqueue(T&& data)
|
||||||
{
|
{
|
||||||
cell_t* cell;
|
cell_t* cell;
|
||||||
size_t pos = enqueue_pos_.load(std::memory_order_relaxed);
|
size_t pos = enqueue_pos_.load(std::memory_order_relaxed);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
cell = &buffer_[pos & buffer_mask_];
|
cell = &buffer_[pos & buffer_mask_];
|
||||||
size_t seq = cell->sequence_.load(std::memory_order_acquire);
|
size_t seq = cell->sequence_.load(std::memory_order_acquire);
|
||||||
intptr_t dif = (intptr_t)seq - (intptr_t)pos;
|
intptr_t dif = (intptr_t)seq - (intptr_t)pos;
|
||||||
if (dif == 0)
|
if (dif == 0)
|
||||||
{
|
{
|
||||||
if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
|
if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (dif < 0)
|
else if (dif < 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pos = enqueue_pos_.load(std::memory_order_relaxed);
|
pos = enqueue_pos_.load(std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cell->data_ = std::move(data);
|
cell->data_ = std::move(data);
|
||||||
cell->sequence_.store(pos + 1, std::memory_order_release);
|
cell->sequence_.store(pos + 1, std::memory_order_release);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dequeue(T& data)
|
bool dequeue(T& data)
|
||||||
{
|
{
|
||||||
cell_t* cell;
|
cell_t* cell;
|
||||||
size_t pos = dequeue_pos_.load(std::memory_order_relaxed);
|
size_t pos = dequeue_pos_.load(std::memory_order_relaxed);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
cell = &buffer_[pos & buffer_mask_];
|
cell = &buffer_[pos & buffer_mask_];
|
||||||
size_t seq =
|
size_t seq =
|
||||||
cell->sequence_.load(std::memory_order_acquire);
|
cell->sequence_.load(std::memory_order_acquire);
|
||||||
intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1);
|
intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1);
|
||||||
if (dif == 0)
|
if (dif == 0)
|
||||||
{
|
{
|
||||||
if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
|
if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (dif < 0)
|
else if (dif < 0)
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
pos = dequeue_pos_.load(std::memory_order_relaxed);
|
pos = dequeue_pos_.load(std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
data = std::move(cell->data_);
|
data = std::move(cell->data_);
|
||||||
cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release);
|
cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct cell_t
|
struct cell_t
|
||||||
{
|
{
|
||||||
std::atomic<size_t> sequence_;
|
std::atomic<size_t> sequence_;
|
||||||
T data_;
|
T data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
static size_t const cacheline_size = 64;
|
static size_t const cacheline_size = 64;
|
||||||
typedef char cacheline_pad_t [cacheline_size];
|
typedef char cacheline_pad_t [cacheline_size];
|
||||||
|
|
||||||
cacheline_pad_t pad0_;
|
cacheline_pad_t pad0_;
|
||||||
cell_t* const buffer_;
|
cell_t* const buffer_;
|
||||||
size_t const buffer_mask_;
|
size_t const buffer_mask_;
|
||||||
cacheline_pad_t pad1_;
|
cacheline_pad_t pad1_;
|
||||||
std::atomic<size_t> enqueue_pos_;
|
std::atomic<size_t> enqueue_pos_;
|
||||||
cacheline_pad_t pad2_;
|
cacheline_pad_t pad2_;
|
||||||
std::atomic<size_t> dequeue_pos_;
|
std::atomic<size_t> dequeue_pos_;
|
||||||
cacheline_pad_t pad3_;
|
cacheline_pad_t pad3_;
|
||||||
|
|
||||||
mpmc_bounded_queue(mpmc_bounded_queue const&);
|
mpmc_bounded_queue(mpmc_bounded_queue const&);
|
||||||
void operator = (mpmc_bounded_queue const&);
|
void operator = (mpmc_bounded_queue const&);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ns details
|
} // ns details
|
||||||
|
@ -32,12 +32,12 @@ namespace details
|
|||||||
{
|
{
|
||||||
struct null_mutex
|
struct null_mutex
|
||||||
{
|
{
|
||||||
void lock() {}
|
void lock() {}
|
||||||
void unlock() {}
|
void unlock() {}
|
||||||
bool try_lock()
|
bool try_lock()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,19 +44,19 @@ inline std::tm localtime(const std::time_t &time_tt)
|
|||||||
{
|
{
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::tm tm;
|
std::tm tm;
|
||||||
localtime_s(&tm, &time_tt);
|
localtime_s(&tm, &time_tt);
|
||||||
#else
|
#else
|
||||||
std::tm tm;
|
std::tm tm;
|
||||||
localtime_r(&time_tt, &tm);
|
localtime_r(&time_tt, &tm);
|
||||||
#endif
|
#endif
|
||||||
return tm;
|
return tm;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::tm localtime()
|
inline std::tm localtime()
|
||||||
{
|
{
|
||||||
std::time_t now_t = time(0);
|
std::time_t now_t = time(0);
|
||||||
return localtime(now_t);
|
return localtime(now_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -64,57 +64,57 @@ inline std::tm gmtime(const std::time_t &time_tt)
|
|||||||
{
|
{
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::tm tm;
|
std::tm tm;
|
||||||
gmtime_s(&tm, &time_tt);
|
gmtime_s(&tm, &time_tt);
|
||||||
#else
|
#else
|
||||||
std::tm tm;
|
std::tm tm;
|
||||||
gmtime_r(&time_tt, &tm);
|
gmtime_r(&time_tt, &tm);
|
||||||
#endif
|
#endif
|
||||||
return tm;
|
return tm;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::tm gmtime()
|
inline std::tm gmtime()
|
||||||
{
|
{
|
||||||
std::time_t now_t = time(0);
|
std::time_t now_t = time(0);
|
||||||
return gmtime(now_t);
|
return gmtime(now_t);
|
||||||
}
|
}
|
||||||
inline bool operator==(const std::tm& tm1, const std::tm& tm2)
|
inline bool operator==(const std::tm& tm1, const std::tm& tm2)
|
||||||
{
|
{
|
||||||
return (tm1.tm_sec == tm2.tm_sec &&
|
return (tm1.tm_sec == tm2.tm_sec &&
|
||||||
tm1.tm_min == tm2.tm_min &&
|
tm1.tm_min == tm2.tm_min &&
|
||||||
tm1.tm_hour == tm2.tm_hour &&
|
tm1.tm_hour == tm2.tm_hour &&
|
||||||
tm1.tm_mday == tm2.tm_mday &&
|
tm1.tm_mday == tm2.tm_mday &&
|
||||||
tm1.tm_mon == tm2.tm_mon &&
|
tm1.tm_mon == tm2.tm_mon &&
|
||||||
tm1.tm_year == tm2.tm_year &&
|
tm1.tm_year == tm2.tm_year &&
|
||||||
tm1.tm_isdst == tm2.tm_isdst);
|
tm1.tm_isdst == tm2.tm_isdst);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
|
inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
|
||||||
{
|
{
|
||||||
return !(tm1 == tm2);
|
return !(tm1 == tm2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
inline const char* eol()
|
inline const char* eol()
|
||||||
{
|
{
|
||||||
return "\r\n";
|
return "\r\n";
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
constexpr inline const char* eol()
|
constexpr inline const char* eol()
|
||||||
{
|
{
|
||||||
return "\n";
|
return "\n";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
inline unsigned short eol_size()
|
inline unsigned short eol_size()
|
||||||
{
|
{
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
constexpr inline unsigned short eol_size()
|
constexpr inline unsigned short eol_size()
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -122,11 +122,11 @@ constexpr inline unsigned short eol_size()
|
|||||||
inline int fopen_s(FILE** fp, const std::string& filename, const char* mode)
|
inline int fopen_s(FILE** fp, const std::string& filename, const char* mode)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
*fp = _fsopen((filename.c_str()), mode, _SH_DENYWR);
|
*fp = _fsopen((filename.c_str()), mode, _SH_DENYWR);
|
||||||
return *fp == nullptr;
|
return *fp == nullptr;
|
||||||
#else
|
#else
|
||||||
*fp = fopen((filename.c_str()), mode);
|
*fp = fopen((filename.c_str()), mode);
|
||||||
return *fp == nullptr;
|
return *fp == nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -137,14 +137,14 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
|
|||||||
{
|
{
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
(void)tm; // avoid unused param warning
|
(void)tm; // avoid unused param warning
|
||||||
DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
|
DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
|
||||||
auto rv = GetDynamicTimeZoneInformation(&tzinfo);
|
auto rv = GetDynamicTimeZoneInformation(&tzinfo);
|
||||||
if (!rv)
|
if (!rv)
|
||||||
return -1;
|
return -1;
|
||||||
return -1 * (tzinfo.Bias + tzinfo.DaylightBias);
|
return -1 * (tzinfo.Bias + tzinfo.DaylightBias);
|
||||||
#else
|
#else
|
||||||
return static_cast<int>(tm.tm_gmtoff / 60);
|
return static_cast<int>(tm.tm_gmtoff / 60);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ namespace details
|
|||||||
class flag_formatter
|
class flag_formatter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~flag_formatter() {}
|
virtual ~flag_formatter() {}
|
||||||
virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0;
|
virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
@ -53,20 +53,20 @@ namespace
|
|||||||
{
|
{
|
||||||
class name_formatter :public flag_formatter
|
class name_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm&) override
|
void format(details::log_msg& msg, const std::tm&) override
|
||||||
{
|
{
|
||||||
msg.formatted << msg.logger_name;
|
msg.formatted << msg.logger_name;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// log level appender
|
// log level appender
|
||||||
class level_formatter :public flag_formatter
|
class level_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm&) override
|
void format(details::log_msg& msg, const std::tm&) override
|
||||||
{
|
{
|
||||||
msg.formatted << level::to_str(msg.level);
|
msg.formatted << level::to_str(msg.level);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
@ -75,88 +75,88 @@ class level_formatter :public flag_formatter
|
|||||||
|
|
||||||
static const char* ampm(const tm& t)
|
static const char* ampm(const tm& t)
|
||||||
{
|
{
|
||||||
return t.tm_hour >= 12 ? "PM" : "AM";
|
return t.tm_hour >= 12 ? "PM" : "AM";
|
||||||
}
|
}
|
||||||
|
|
||||||
static int to12h(const tm& t)
|
static int to12h(const tm& t)
|
||||||
{
|
{
|
||||||
return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour;
|
return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Abbreviated weekday name
|
//Abbreviated weekday name
|
||||||
static const std::string days[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
static const std::string days[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||||
class a_formatter :public flag_formatter
|
class a_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << days[tm_time.tm_wday];
|
msg.formatted << days[tm_time.tm_wday];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Full weekday name
|
//Full weekday name
|
||||||
static const std::string full_days[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
|
static const std::string full_days[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
|
||||||
class A_formatter :public flag_formatter
|
class A_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << full_days[tm_time.tm_wday];
|
msg.formatted << full_days[tm_time.tm_wday];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Abbreviated month
|
//Abbreviated month
|
||||||
static const std::string months[] { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" };
|
static const std::string months[] { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" };
|
||||||
class b_formatter :public flag_formatter
|
class b_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted<< months[tm_time.tm_mon];
|
msg.formatted<< months[tm_time.tm_mon];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Full month name
|
//Full month name
|
||||||
static const std::string full_months[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
|
static const std::string full_months[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
|
||||||
class B_formatter :public flag_formatter
|
class B_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << full_months[tm_time.tm_mon];
|
msg.formatted << full_months[tm_time.tm_mon];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//write 2 ints seperated by sep with padding of 2
|
//write 2 ints seperated by sep with padding of 2
|
||||||
static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, char sep)
|
static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, char sep)
|
||||||
{
|
{
|
||||||
w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0');
|
w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0');
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
//write 3 ints seperated by sep with padding of 2
|
//write 3 ints seperated by sep with padding of 2
|
||||||
static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v3, char sep)
|
static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v3, char sep)
|
||||||
{
|
{
|
||||||
w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0') << sep << fmt::pad(v3, 2, '0');
|
w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0') << sep << fmt::pad(v3, 2, '0');
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Date and time representation (Thu Aug 23 15:35:46 2014)
|
//Date and time representation (Thu Aug 23 15:35:46 2014)
|
||||||
class c_formatter :public flag_formatter
|
class c_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << days[tm_time.tm_wday] << ' ' << months[tm_time.tm_mon] << ' ' << tm_time.tm_mday << ' ';
|
msg.formatted << days[tm_time.tm_wday] << ' ' << months[tm_time.tm_mon] << ' ' << tm_time.tm_mday << ' ';
|
||||||
pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900;
|
pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// year - 2 digit
|
// year - 2 digit
|
||||||
class C_formatter :public flag_formatter
|
class C_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0');
|
msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -164,122 +164,122 @@ class C_formatter :public flag_formatter
|
|||||||
// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01
|
// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01
|
||||||
class D_formatter :public flag_formatter
|
class D_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100, '/');
|
pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100, '/');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// year - 4 digit
|
// year - 4 digit
|
||||||
class Y_formatter :public flag_formatter
|
class Y_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << tm_time.tm_year + 1900;
|
msg.formatted << tm_time.tm_year + 1900;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// month 1-12
|
// month 1-12
|
||||||
class m_formatter :public flag_formatter
|
class m_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0');
|
msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// day of month 1-31
|
// day of month 1-31
|
||||||
class d_formatter :public flag_formatter
|
class d_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0');
|
msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// hours in 24 format 0-23
|
// hours in 24 format 0-23
|
||||||
class H_formatter :public flag_formatter
|
class H_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0');
|
msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// hours in 12 format 1-12
|
// hours in 12 format 1-12
|
||||||
class I_formatter :public flag_formatter
|
class I_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << fmt::pad(to12h(tm_time), 2, '0');
|
msg.formatted << fmt::pad(to12h(tm_time), 2, '0');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ninutes 0-59
|
// ninutes 0-59
|
||||||
class M_formatter :public flag_formatter
|
class M_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << fmt::pad(tm_time.tm_min, 2, '0');
|
msg.formatted << fmt::pad(tm_time.tm_min, 2, '0');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// seconds 0-59
|
// seconds 0-59
|
||||||
class S_formatter :public flag_formatter
|
class S_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0');
|
msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// milliseconds
|
// milliseconds
|
||||||
class e_formatter :public flag_formatter
|
class e_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm&) override
|
void format(details::log_msg& msg, const std::tm&) override
|
||||||
{
|
{
|
||||||
auto duration = msg.time.time_since_epoch();
|
auto duration = msg.time.time_since_epoch();
|
||||||
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
|
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
|
||||||
msg.formatted << fmt::pad(static_cast<int>(millis), 3, '0');
|
msg.formatted << fmt::pad(static_cast<int>(millis), 3, '0');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// AM/PM
|
// AM/PM
|
||||||
class p_formatter :public flag_formatter
|
class p_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
msg.formatted << ampm(tm_time);
|
msg.formatted << ampm(tm_time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 12 hour clock 02:55:02 pm
|
// 12 hour clock 02:55:02 pm
|
||||||
class r_formatter :public flag_formatter
|
class r_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << ampm(tm_time);
|
pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << ampm(tm_time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 24-hour HH:MM time, equivalent to %H:%M
|
// 24-hour HH:MM time, equivalent to %H:%M
|
||||||
class R_formatter :public flag_formatter
|
class R_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':');
|
pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
|
// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
|
||||||
class T_formatter :public flag_formatter
|
class T_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':');
|
pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -287,44 +287,44 @@ class T_formatter :public flag_formatter
|
|||||||
class z_formatter :public flag_formatter
|
class z_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const std::chrono::seconds cache_refresh = std::chrono::seconds(5);
|
const std::chrono::seconds cache_refresh = std::chrono::seconds(5);
|
||||||
|
|
||||||
z_formatter() :_last_update(std::chrono::seconds(0)) {}
|
z_formatter() :_last_update(std::chrono::seconds(0)) {}
|
||||||
z_formatter(const z_formatter&) = delete;
|
z_formatter(const z_formatter&) = delete;
|
||||||
z_formatter& operator=(const z_formatter&) = delete;
|
z_formatter& operator=(const z_formatter&) = delete;
|
||||||
|
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
int total_minutes = get_cached_offset(msg, tm_time);
|
int total_minutes = get_cached_offset(msg, tm_time);
|
||||||
#else
|
#else
|
||||||
// No need to chache under gcc,
|
// No need to chache under gcc,
|
||||||
// it is very fast (already stored in tm.tm_gmtoff)
|
// it is very fast (already stored in tm.tm_gmtoff)
|
||||||
int total_minutes = os::utc_minutes_offset(tm_time);
|
int total_minutes = os::utc_minutes_offset(tm_time);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int h = total_minutes / 60;
|
int h = total_minutes / 60;
|
||||||
int m = total_minutes % 60;
|
int m = total_minutes % 60;
|
||||||
char sign = h >= 0 ? '+' : '-';
|
char sign = h >= 0 ? '+' : '-';
|
||||||
msg.formatted << sign;
|
msg.formatted << sign;
|
||||||
pad_n_join(msg.formatted, h, m, ':');
|
pad_n_join(msg.formatted, h, m, ':');
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
log_clock::time_point _last_update;
|
log_clock::time_point _last_update;
|
||||||
int _offset_minutes;
|
int _offset_minutes;
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
|
|
||||||
int get_cached_offset(const log_msg& msg, const std::tm& tm_time)
|
int get_cached_offset(const log_msg& msg, const std::tm& tm_time)
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
std::lock_guard<std::mutex> l(_mutex);
|
std::lock_guard<std::mutex> l(_mutex);
|
||||||
if (msg.time - _last_update >= cache_refresh)
|
if (msg.time - _last_update >= cache_refresh)
|
||||||
{
|
{
|
||||||
_offset_minutes = os::utc_minutes_offset(tm_time);
|
_offset_minutes = os::utc_minutes_offset(tm_time);
|
||||||
_last_update = msg.time;
|
_last_update = msg.time;
|
||||||
}
|
}
|
||||||
return _offset_minutes;
|
return _offset_minutes;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -332,32 +332,32 @@ private:
|
|||||||
//Thread id
|
//Thread id
|
||||||
class t_formatter :public flag_formatter
|
class t_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm&) override
|
void format(details::log_msg& msg, const std::tm&) override
|
||||||
{
|
{
|
||||||
msg.formatted << std::hash<std::thread::id>()(std::this_thread::get_id());
|
msg.formatted << std::hash<std::thread::id>()(std::this_thread::get_id());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class v_formatter :public flag_formatter
|
class v_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm&) override
|
void format(details::log_msg& msg, const std::tm&) override
|
||||||
{
|
{
|
||||||
msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
|
msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ch_formatter :public flag_formatter
|
class ch_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ch_formatter(char ch) : _ch(ch)
|
explicit ch_formatter(char ch) : _ch(ch)
|
||||||
{}
|
{}
|
||||||
void format(details::log_msg& msg, const std::tm&) override
|
void format(details::log_msg& msg, const std::tm&) override
|
||||||
{
|
{
|
||||||
msg.formatted << _ch;
|
msg.formatted << _ch;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
char _ch;
|
char _ch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -365,54 +365,54 @@ private:
|
|||||||
class aggregate_formatter :public flag_formatter
|
class aggregate_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
aggregate_formatter()
|
aggregate_formatter()
|
||||||
{}
|
{}
|
||||||
void add_ch(char ch)
|
void add_ch(char ch)
|
||||||
{
|
{
|
||||||
_str += ch;
|
_str += ch;
|
||||||
}
|
}
|
||||||
void format(details::log_msg& msg, const std::tm&) override
|
void format(details::log_msg& msg, const std::tm&) override
|
||||||
{
|
{
|
||||||
msg.formatted << _str;
|
msg.formatted << _str;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::string _str;
|
std::string _str;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Full info formatter
|
// Full info formatter
|
||||||
// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
|
// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
|
||||||
class full_formatter :public flag_formatter
|
class full_formatter :public flag_formatter
|
||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||||
{
|
{
|
||||||
auto duration = msg.time.time_since_epoch();
|
auto duration = msg.time.time_since_epoch();
|
||||||
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
|
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
|
||||||
|
|
||||||
/* Slower version(while still very fast - about 3.2 million lines/sec under 10 threads),
|
/* Slower version(while still very fast - about 3.2 million lines/sec under 10 threads),
|
||||||
msg.formatted.write("[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] {} ",
|
msg.formatted.write("[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] {} ",
|
||||||
tm_time.tm_year + 1900,
|
tm_time.tm_year + 1900,
|
||||||
tm_time.tm_mon + 1,
|
tm_time.tm_mon + 1,
|
||||||
tm_time.tm_mday,
|
tm_time.tm_mday,
|
||||||
tm_time.tm_hour,
|
tm_time.tm_hour,
|
||||||
tm_time.tm_min,
|
tm_time.tm_min,
|
||||||
tm_time.tm_sec,
|
tm_time.tm_sec,
|
||||||
static_cast<int>(millis),
|
static_cast<int>(millis),
|
||||||
msg.logger_name,
|
msg.logger_name,
|
||||||
level::to_str(msg.level),
|
level::to_str(msg.level),
|
||||||
msg.raw.str());*/
|
msg.raw.str());*/
|
||||||
|
|
||||||
// Faster (albeit uglier) way to format the line (5.6 million lines/sec under 10 threads)
|
// Faster (albeit uglier) way to format the line (5.6 million lines/sec under 10 threads)
|
||||||
msg.formatted << '[' << static_cast<unsigned int>(tm_time.tm_year + 1900) << '-'
|
msg.formatted << '[' << static_cast<unsigned int>(tm_time.tm_year + 1900) << '-'
|
||||||
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_mon + 1), 2, '0') << '-'
|
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_mon + 1), 2, '0') << '-'
|
||||||
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_mday), 2, '0') << ' '
|
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_mday), 2, '0') << ' '
|
||||||
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_hour), 2, '0') << ':'
|
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_hour), 2, '0') << ':'
|
||||||
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_min), 2, '0') << ':'
|
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_min), 2, '0') << ':'
|
||||||
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.'
|
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.'
|
||||||
<< fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] ";
|
<< fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] ";
|
||||||
|
|
||||||
msg.formatted << '[' << msg.logger_name << "] [" << level::to_str(msg.level) << "] ";
|
msg.formatted << '[' << msg.logger_name << "] [" << level::to_str(msg.level) << "] ";
|
||||||
msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
|
msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -422,168 +422,168 @@ class full_formatter :public flag_formatter
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern)
|
inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern)
|
||||||
{
|
{
|
||||||
compile_pattern(pattern);
|
compile_pattern(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::pattern_formatter::compile_pattern(const std::string& pattern)
|
inline void spdlog::pattern_formatter::compile_pattern(const std::string& pattern)
|
||||||
{
|
{
|
||||||
auto end = pattern.end();
|
auto end = pattern.end();
|
||||||
std::unique_ptr<details::aggregate_formatter> user_chars;
|
std::unique_ptr<details::aggregate_formatter> user_chars;
|
||||||
for (auto it = pattern.begin(); it != end; ++it)
|
for (auto it = pattern.begin(); it != end; ++it)
|
||||||
{
|
{
|
||||||
if (*it == '%')
|
if (*it == '%')
|
||||||
{
|
{
|
||||||
if (user_chars) //append user chars found so far
|
if (user_chars) //append user chars found so far
|
||||||
_formatters.push_back(std::move(user_chars));
|
_formatters.push_back(std::move(user_chars));
|
||||||
|
|
||||||
if (++it != end)
|
if (++it != end)
|
||||||
handle_flag(*it);
|
handle_flag(*it);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else // chars not following the % sign should be displayed as is
|
else // chars not following the % sign should be displayed as is
|
||||||
{
|
{
|
||||||
if (!user_chars)
|
if (!user_chars)
|
||||||
user_chars = std::unique_ptr<details::aggregate_formatter>(new details::aggregate_formatter());
|
user_chars = std::unique_ptr<details::aggregate_formatter>(new details::aggregate_formatter());
|
||||||
user_chars->add_ch(*it);
|
user_chars->add_ch(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (user_chars) //append raw chars found so far
|
if (user_chars) //append raw chars found so far
|
||||||
{
|
{
|
||||||
_formatters.push_back(std::move(user_chars));
|
_formatters.push_back(std::move(user_chars));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
inline void spdlog::pattern_formatter::handle_flag(char flag)
|
inline void spdlog::pattern_formatter::handle_flag(char flag)
|
||||||
{
|
{
|
||||||
switch (flag)
|
switch (flag)
|
||||||
{
|
{
|
||||||
// logger name
|
// logger name
|
||||||
case 'n':
|
case 'n':
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::name_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::name_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::level_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::level_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('t') :
|
case('t') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::t_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::t_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('v') :
|
case('v') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::v_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::v_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('a') :
|
case('a') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::a_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::a_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('A') :
|
case('A') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::A_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::A_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('b') :
|
case('b') :
|
||||||
case('h') :
|
case('h') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::b_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::b_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('B') :
|
case('B') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::B_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::B_formatter()));
|
||||||
break;
|
break;
|
||||||
case('c') :
|
case('c') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::c_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::c_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('C') :
|
case('C') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::C_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::C_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('Y') :
|
case('Y') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::Y_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::Y_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('D') :
|
case('D') :
|
||||||
case('x') :
|
case('x') :
|
||||||
|
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::D_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::D_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('m') :
|
case('m') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::m_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::m_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('d') :
|
case('d') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::d_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::d_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('H') :
|
case('H') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::H_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::H_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('I') :
|
case('I') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::I_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::I_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('M') :
|
case('M') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::M_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::M_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('S') :
|
case('S') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::S_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::S_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('e') :
|
case('e') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::e_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::e_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('p') :
|
case('p') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::p_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::p_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('r') :
|
case('r') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::r_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::r_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('R') :
|
case('R') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::R_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::R_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('T') :
|
case('T') :
|
||||||
case('X') :
|
case('X') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::T_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::T_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case('z') :
|
case('z') :
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::z_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::z_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ('+'):
|
case ('+'):
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::full_formatter()));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::full_formatter()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: //Unkown flag appears as is
|
default: //Unkown flag appears as is
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter('%')));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter('%')));
|
||||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter(flag)));
|
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter(flag)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void spdlog::pattern_formatter::format(details::log_msg& msg)
|
inline void spdlog::pattern_formatter::format(details::log_msg& msg)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time));
|
auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time));
|
||||||
for (auto &f : _formatters)
|
for (auto &f : _formatters)
|
||||||
{
|
{
|
||||||
f->format(msg, tm_time);
|
f->format(msg, tm_time);
|
||||||
}
|
}
|
||||||
//write eol
|
//write eol
|
||||||
msg.formatted << details::os::eol();
|
msg.formatted << details::os::eol();
|
||||||
}
|
}
|
||||||
catch(const details::fmt::FormatError& e)
|
catch(const details::fmt::FormatError& e)
|
||||||
{
|
{
|
||||||
throw spdlog_ex(details::fmt::format("formatting error while processing format string: {}", e.what()));
|
throw spdlog_ex(details::fmt::format("formatting error while processing format string: {}", e.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,114 +44,114 @@ namespace details
|
|||||||
class registry
|
class registry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<logger> get(const std::string& logger_name)
|
std::shared_ptr<logger> get(const std::string& logger_name)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
auto found = _loggers.find(logger_name);
|
auto found = _loggers.find(logger_name);
|
||||||
return found == _loggers.end() ? nullptr : found->second;
|
return found == _loggers.end() ? nullptr : found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class It>
|
template<class It>
|
||||||
std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
|
std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
//If already exists, just return it
|
//If already exists, just return it
|
||||||
auto found = _loggers.find(logger_name);
|
auto found = _loggers.find(logger_name);
|
||||||
if (found != _loggers.end())
|
if (found != _loggers.end())
|
||||||
return found->second;
|
return found->second;
|
||||||
std::shared_ptr<logger> new_logger;
|
std::shared_ptr<logger> new_logger;
|
||||||
if (_async_mode)
|
if (_async_mode)
|
||||||
new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size);
|
new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size);
|
||||||
else
|
else
|
||||||
new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
|
new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
|
||||||
|
|
||||||
if (_formatter)
|
if (_formatter)
|
||||||
new_logger->set_formatter(_formatter);
|
new_logger->set_formatter(_formatter);
|
||||||
new_logger->set_level(_level);
|
new_logger->set_level(_level);
|
||||||
_loggers[logger_name] = new_logger;
|
_loggers[logger_name] = new_logger;
|
||||||
return new_logger;
|
return new_logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drop(const std::string& logger_name)
|
void drop(const std::string& logger_name)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
_loggers.erase(logger_name);
|
_loggers.erase(logger_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks)
|
std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks)
|
||||||
{
|
{
|
||||||
return create(logger_name, sinks.begin(), sinks.end());
|
return create(logger_name, sinks.begin(), sinks.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<logger> create(const std::string& logger_name, sink_ptr sink)
|
std::shared_ptr<logger> create(const std::string& logger_name, sink_ptr sink)
|
||||||
{
|
{
|
||||||
return create(logger_name, { sink });
|
return create(logger_name, { sink });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void formatter(formatter_ptr f)
|
void formatter(formatter_ptr f)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
_formatter = f;
|
_formatter = f;
|
||||||
for (auto& l : _loggers)
|
for (auto& l : _loggers)
|
||||||
l.second->set_formatter(_formatter);
|
l.second->set_formatter(_formatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void set_pattern(const std::string& pattern)
|
void set_pattern(const std::string& pattern)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
_formatter = std::make_shared<pattern_formatter>(pattern);
|
_formatter = std::make_shared<pattern_formatter>(pattern);
|
||||||
for (auto& l : _loggers)
|
for (auto& l : _loggers)
|
||||||
l.second->set_formatter(_formatter);
|
l.second->set_formatter(_formatter);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_level(level::level_enum log_level)
|
void set_level(level::level_enum log_level)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
for (auto& l : _loggers)
|
for (auto& l : _loggers)
|
||||||
l.second->set_level(log_level);
|
l.second->set_level(log_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_async_mode(size_t q_size)
|
void set_async_mode(size_t q_size)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
_async_mode = true;
|
_async_mode = true;
|
||||||
_async_q_size = q_size;
|
_async_q_size = q_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_sync_mode()
|
void set_sync_mode()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
_async_mode = false;
|
_async_mode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_all()
|
void stop_all()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
_level = level::off;
|
_level = level::off;
|
||||||
for (auto& l : _loggers)
|
for (auto& l : _loggers)
|
||||||
l.second->stop();
|
l.second->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static registry& instance()
|
static registry& instance()
|
||||||
{
|
{
|
||||||
static registry s_instance;
|
static registry s_instance;
|
||||||
return s_instance;
|
return s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
registry() = default;
|
registry() = default;
|
||||||
registry(const registry&) = delete;
|
registry(const registry&) = delete;
|
||||||
registry& operator=(const registry&) = delete;
|
registry& operator=(const registry&) = delete;
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
std::unordered_map <std::string, std::shared_ptr<logger>> _loggers;
|
std::unordered_map <std::string, std::shared_ptr<logger>> _loggers;
|
||||||
formatter_ptr _formatter;
|
formatter_ptr _formatter;
|
||||||
level::level_enum _level = level::info;
|
level::level_enum _level = level::info;
|
||||||
bool _async_mode = false;
|
bool _async_mode = false;
|
||||||
size_t _async_q_size = 0;
|
size_t _async_q_size = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,62 +34,62 @@
|
|||||||
|
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::get(const std::string& name)
|
inline std::shared_ptr<spdlog::logger> spdlog::get(const std::string& name)
|
||||||
{
|
{
|
||||||
return details::registry::instance().get(name);
|
return details::registry::instance().get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::drop(const std::string &name)
|
inline void spdlog::drop(const std::string &name)
|
||||||
{
|
{
|
||||||
details::registry::instance().drop(name);
|
details::registry::instance().drop(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create multi/single threaded rotating file logger
|
// Create multi/single threaded rotating file logger
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool auto_flush)
|
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool auto_flush)
|
||||||
{
|
{
|
||||||
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, "txt", max_file_size, max_files, auto_flush);
|
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, "txt", max_file_size, max_files, auto_flush);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool auto_flush)
|
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool auto_flush)
|
||||||
{
|
{
|
||||||
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, "txt", max_file_size, max_files, auto_flush);
|
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, "txt", max_file_size, max_files, auto_flush);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create file logger which creates new file at midnight):
|
// Create file logger which creates new file at midnight):
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const std::string& filename, bool auto_flush)
|
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const std::string& filename, bool auto_flush)
|
||||||
{
|
{
|
||||||
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, "txt", auto_flush);
|
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, "txt", auto_flush);
|
||||||
}
|
}
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const std::string& filename, bool auto_flush)
|
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const std::string& filename, bool auto_flush)
|
||||||
{
|
{
|
||||||
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, "txt", auto_flush);
|
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, "txt", auto_flush);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create stdout/stderr loggers
|
// Create stdout/stderr loggers
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name)
|
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name)
|
||||||
{
|
{
|
||||||
return create<spdlog::sinks::stdout_sink_mt>(logger_name);
|
return create<spdlog::sinks::stdout_sink_mt>(logger_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name)
|
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name)
|
||||||
{
|
{
|
||||||
return create<spdlog::sinks::stdout_sink_st>(logger_name);
|
return create<spdlog::sinks::stdout_sink_st>(logger_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name)
|
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name)
|
||||||
{
|
{
|
||||||
return create<spdlog::sinks::stderr_sink_mt>(logger_name);
|
return create<spdlog::sinks::stderr_sink_mt>(logger_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name)
|
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name)
|
||||||
{
|
{
|
||||||
return create<spdlog::sinks::stderr_sink_st>(logger_name);
|
return create<spdlog::sinks::stderr_sink_st>(logger_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
// Create syslog logger
|
// Create syslog logger
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option)
|
inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option)
|
||||||
{
|
{
|
||||||
return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option);
|
return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -98,51 +98,51 @@ inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string&
|
|||||||
|
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks)
|
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks)
|
||||||
{
|
{
|
||||||
return details::registry::instance().create(logger_name, sinks);
|
return details::registry::instance().create(logger_name, sinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename Sink, typename... Args>
|
template <typename Sink, typename... Args>
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const Args&... args)
|
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const Args&... args)
|
||||||
{
|
{
|
||||||
sink_ptr sink = std::make_shared<Sink>(args...);
|
sink_ptr sink = std::make_shared<Sink>(args...);
|
||||||
return details::registry::instance().create(logger_name, { sink });
|
return details::registry::instance().create(logger_name, { sink });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class It>
|
template<class It>
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
|
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
|
||||||
{
|
{
|
||||||
return details::registry::instance().create(logger_name, sinks_begin, sinks_end);
|
return details::registry::instance().create(logger_name, sinks_begin, sinks_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::set_formatter(spdlog::formatter_ptr f)
|
inline void spdlog::set_formatter(spdlog::formatter_ptr f)
|
||||||
{
|
{
|
||||||
details::registry::instance().formatter(f);
|
details::registry::instance().formatter(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::set_pattern(const std::string& format_string)
|
inline void spdlog::set_pattern(const std::string& format_string)
|
||||||
{
|
{
|
||||||
return details::registry::instance().set_pattern(format_string);
|
return details::registry::instance().set_pattern(format_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::set_level(level::level_enum log_level)
|
inline void spdlog::set_level(level::level_enum log_level)
|
||||||
{
|
{
|
||||||
return details::registry::instance().set_level(log_level);
|
return details::registry::instance().set_level(log_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void spdlog::set_async_mode(size_t queue_size)
|
inline void spdlog::set_async_mode(size_t queue_size)
|
||||||
{
|
{
|
||||||
details::registry::instance().set_async_mode(queue_size);
|
details::registry::instance().set_async_mode(queue_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::set_sync_mode()
|
inline void spdlog::set_sync_mode()
|
||||||
{
|
{
|
||||||
details::registry::instance().set_sync_mode();
|
details::registry::instance().set_sync_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::stop()
|
inline void spdlog::stop()
|
||||||
{
|
{
|
||||||
return details::registry::instance().stop_all();
|
return details::registry::instance().stop_all();
|
||||||
}
|
}
|
||||||
|
@ -34,23 +34,23 @@ class flag_formatter;
|
|||||||
class formatter
|
class formatter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~formatter() {}
|
virtual ~formatter() {}
|
||||||
virtual void format(details::log_msg& msg) = 0;
|
virtual void format(details::log_msg& msg) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class pattern_formatter : public formatter
|
class pattern_formatter : public formatter
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit pattern_formatter(const std::string& pattern);
|
explicit pattern_formatter(const std::string& pattern);
|
||||||
pattern_formatter(const pattern_formatter&) = delete;
|
pattern_formatter(const pattern_formatter&) = delete;
|
||||||
pattern_formatter& operator=(const pattern_formatter&) = delete;
|
pattern_formatter& operator=(const pattern_formatter&) = delete;
|
||||||
void format(details::log_msg& msg) override;
|
void format(details::log_msg& msg) override;
|
||||||
private:
|
private:
|
||||||
const std::string _pattern;
|
const std::string _pattern;
|
||||||
std::vector<std::unique_ptr<details::flag_formatter>> _formatters;
|
std::vector<std::unique_ptr<details::flag_formatter>> _formatters;
|
||||||
void handle_flag(char flag);
|
void handle_flag(char flag);
|
||||||
void compile_pattern(const std::string& pattern);
|
void compile_pattern(const std::string& pattern);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,88 +47,88 @@ class line_logger;
|
|||||||
class logger
|
class logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
logger(const std::string& logger_name, sink_ptr single_sink);
|
logger(const std::string& logger_name, sink_ptr single_sink);
|
||||||
logger(const std::string& name, sinks_init_list);
|
logger(const std::string& name, sinks_init_list);
|
||||||
template<class It>
|
template<class It>
|
||||||
logger(const std::string& name, const It& begin, const It& end);
|
logger(const std::string& name, const It& begin, const It& end);
|
||||||
|
|
||||||
virtual ~logger();
|
virtual ~logger();
|
||||||
logger(const logger&) = delete;
|
logger(const logger&) = delete;
|
||||||
logger& operator=(const logger&) = delete;
|
logger& operator=(const logger&) = delete;
|
||||||
|
|
||||||
void set_level(level::level_enum);
|
void set_level(level::level_enum);
|
||||||
level::level_enum level() const;
|
level::level_enum level() const;
|
||||||
|
|
||||||
const std::string& name() const;
|
const std::string& name() const;
|
||||||
bool should_log(level::level_enum) const;
|
bool should_log(level::level_enum) const;
|
||||||
|
|
||||||
//Stop logging
|
//Stop logging
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
details::line_logger trace(const char* fmt, const Args&... args);
|
details::line_logger trace(const char* fmt, const Args&... args);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
details::line_logger debug(const char* fmt, const Args&... args);
|
details::line_logger debug(const char* fmt, const Args&... args);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
details::line_logger info(const char* fmt, const Args&... args);
|
details::line_logger info(const char* fmt, const Args&... args);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
details::line_logger notice(const char* fmt, const Args&... args);
|
details::line_logger notice(const char* fmt, const Args&... args);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
details::line_logger warn(const char* fmt, const Args&... args);
|
details::line_logger warn(const char* fmt, const Args&... args);
|
||||||
|
|
||||||
template <typename... Args>details::line_logger error(const char* fmt, const Args&... args);
|
template <typename... Args>details::line_logger error(const char* fmt, const Args&... args);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
details::line_logger critical(const char* fmt, const Args&... args);
|
details::line_logger critical(const char* fmt, const Args&... args);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
details::line_logger alert(const char* fmt, const Args&... args);
|
details::line_logger alert(const char* fmt, const Args&... args);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
details::line_logger emerg(const char* fmt, const Args&... args);
|
details::line_logger emerg(const char* fmt, const Args&... args);
|
||||||
|
|
||||||
|
|
||||||
//API to support logger.info() << ".." call style
|
//API to support logger.info() << ".." call style
|
||||||
details::line_logger trace();
|
details::line_logger trace();
|
||||||
details::line_logger debug();
|
details::line_logger debug();
|
||||||
details::line_logger info();
|
details::line_logger info();
|
||||||
details::line_logger notice();
|
details::line_logger notice();
|
||||||
details::line_logger warn();
|
details::line_logger warn();
|
||||||
details::line_logger error();
|
details::line_logger error();
|
||||||
details::line_logger critical();
|
details::line_logger critical();
|
||||||
details::line_logger alert();
|
details::line_logger alert();
|
||||||
details::line_logger emerg();
|
details::line_logger emerg();
|
||||||
|
|
||||||
|
|
||||||
// Create log message with the given level, no matter what is the actual logger's level
|
// Create log message with the given level, no matter what is the actual logger's level
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
details::line_logger force_log(level::level_enum lvl, const char* fmt, const Args&... args);
|
details::line_logger force_log(level::level_enum lvl, const char* fmt, const Args&... args);
|
||||||
|
|
||||||
// Set the format of the log messages from this logger
|
// Set the format of the log messages from this logger
|
||||||
void set_pattern(const std::string&);
|
void set_pattern(const std::string&);
|
||||||
void set_formatter(formatter_ptr);
|
void set_formatter(formatter_ptr);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _log_msg(details::log_msg&);
|
virtual void _log_msg(details::log_msg&);
|
||||||
virtual void _set_pattern(const std::string&);
|
virtual void _set_pattern(const std::string&);
|
||||||
virtual void _set_formatter(formatter_ptr);
|
virtual void _set_formatter(formatter_ptr);
|
||||||
virtual void _stop();
|
virtual void _stop();
|
||||||
details::line_logger _log_if_enabled(level::level_enum lvl);
|
details::line_logger _log_if_enabled(level::level_enum lvl);
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
details::line_logger _log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args);
|
details::line_logger _log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args);
|
||||||
|
|
||||||
|
|
||||||
friend details::line_logger;
|
friend details::line_logger;
|
||||||
std::string _name;
|
std::string _name;
|
||||||
std::vector<sink_ptr> _sinks;
|
std::vector<sink_ptr> _sinks;
|
||||||
formatter_ptr _formatter;
|
formatter_ptr _formatter;
|
||||||
std::atomic_int _level;
|
std::atomic_int _level;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -46,22 +46,22 @@ template<class Mutex>
|
|||||||
class base_sink:public sink
|
class base_sink:public sink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
base_sink():_mutex() {}
|
base_sink():_mutex() {}
|
||||||
virtual ~base_sink() = default;
|
virtual ~base_sink() = default;
|
||||||
|
|
||||||
base_sink(const base_sink&) = delete;
|
base_sink(const base_sink&) = delete;
|
||||||
base_sink& operator=(const base_sink&) = delete;
|
base_sink& operator=(const base_sink&) = delete;
|
||||||
|
|
||||||
void log(const details::log_msg& msg) override
|
void log(const details::log_msg& msg) override
|
||||||
{
|
{
|
||||||
std::lock_guard<Mutex> lock(_mutex);
|
std::lock_guard<Mutex> lock(_mutex);
|
||||||
_sink_it(msg);
|
_sink_it(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _sink_it(const details::log_msg& msg) = 0;
|
virtual void _sink_it(const details::log_msg& msg) = 0;
|
||||||
Mutex _mutex;
|
Mutex _mutex;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,20 +43,20 @@ template<class Mutex>
|
|||||||
class simple_file_sink : public base_sink<Mutex>
|
class simple_file_sink : public base_sink<Mutex>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit simple_file_sink(const std::string &filename,
|
explicit simple_file_sink(const std::string &filename,
|
||||||
bool auto_flush=false):
|
bool auto_flush=false):
|
||||||
_file_helper(auto_flush)
|
_file_helper(auto_flush)
|
||||||
{
|
{
|
||||||
_file_helper.open(filename);
|
_file_helper.open(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _sink_it(const details::log_msg& msg) override
|
void _sink_it(const details::log_msg& msg) override
|
||||||
{
|
{
|
||||||
_file_helper.write(msg);
|
_file_helper.write(msg);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
details::file_helper _file_helper;
|
details::file_helper _file_helper;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef simple_file_sink<std::mutex> simple_file_sink_mt;
|
typedef simple_file_sink<std::mutex> simple_file_sink_mt;
|
||||||
@ -69,80 +69,80 @@ template<class Mutex>
|
|||||||
class rotating_file_sink : public base_sink<Mutex>
|
class rotating_file_sink : public base_sink<Mutex>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
rotating_file_sink(const std::string &base_filename, const std::string &extension,
|
rotating_file_sink(const std::string &base_filename, const std::string &extension,
|
||||||
std::size_t max_size, std::size_t max_files,
|
std::size_t max_size, std::size_t max_files,
|
||||||
bool auto_flush=false):
|
bool auto_flush=false):
|
||||||
_base_filename(base_filename),
|
_base_filename(base_filename),
|
||||||
_extension(extension),
|
_extension(extension),
|
||||||
_max_size(max_size),
|
_max_size(max_size),
|
||||||
_max_files(max_files),
|
_max_files(max_files),
|
||||||
_current_size(0),
|
_current_size(0),
|
||||||
_file_helper(auto_flush)
|
_file_helper(auto_flush)
|
||||||
{
|
{
|
||||||
_file_helper.open(calc_filename(_base_filename, 0, _extension));
|
_file_helper.open(calc_filename(_base_filename, 0, _extension));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _sink_it(const details::log_msg& msg) override
|
void _sink_it(const details::log_msg& msg) override
|
||||||
{
|
{
|
||||||
_current_size += msg.formatted.size();
|
_current_size += msg.formatted.size();
|
||||||
if (_current_size > _max_size)
|
if (_current_size > _max_size)
|
||||||
{
|
{
|
||||||
_rotate();
|
_rotate();
|
||||||
_current_size = msg.formatted.size();
|
_current_size = msg.formatted.size();
|
||||||
}
|
}
|
||||||
_file_helper.write(msg);
|
_file_helper.write(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string calc_filename(const std::string& filename, std::size_t index, const std::string& extension)
|
static std::string calc_filename(const std::string& filename, std::size_t index, const std::string& extension)
|
||||||
{
|
{
|
||||||
details::fmt::MemoryWriter w;
|
details::fmt::MemoryWriter w;
|
||||||
if (index)
|
if (index)
|
||||||
w.write("{}.{}.{}", filename, index, extension);
|
w.write("{}.{}.{}", filename, index, extension);
|
||||||
else
|
else
|
||||||
w.write("{}.{}", filename, extension);
|
w.write("{}.{}", filename, extension);
|
||||||
return w.str();
|
return w.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Rotate files:
|
// Rotate files:
|
||||||
// log.txt -> log.1.txt
|
// log.txt -> log.1.txt
|
||||||
// log.1.txt -> log2.txt
|
// log.1.txt -> log2.txt
|
||||||
// log.2.txt -> log3.txt
|
// log.2.txt -> log3.txt
|
||||||
// log.3.txt -> delete
|
// log.3.txt -> delete
|
||||||
|
|
||||||
|
|
||||||
void _rotate()
|
void _rotate()
|
||||||
{
|
{
|
||||||
_file_helper.close();
|
_file_helper.close();
|
||||||
for (auto i = _max_files; i > 0; --i)
|
for (auto i = _max_files; i > 0; --i)
|
||||||
{
|
{
|
||||||
std::string src = calc_filename(_base_filename, i - 1, _extension);
|
std::string src = calc_filename(_base_filename, i - 1, _extension);
|
||||||
std::string target = calc_filename(_base_filename, i, _extension);
|
std::string target = calc_filename(_base_filename, i, _extension);
|
||||||
|
|
||||||
if (details::file_helper::file_exists(target))
|
if (details::file_helper::file_exists(target))
|
||||||
{
|
{
|
||||||
if (std::remove(target.c_str()) != 0)
|
if (std::remove(target.c_str()) != 0)
|
||||||
{
|
{
|
||||||
throw spdlog_ex("rotating_file_sink: failed removing " + target);
|
throw spdlog_ex("rotating_file_sink: failed removing " + target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (details::file_helper::file_exists(src) && std::rename(src.c_str(), target.c_str()))
|
if (details::file_helper::file_exists(src) && std::rename(src.c_str(), target.c_str()))
|
||||||
{
|
{
|
||||||
throw spdlog_ex("rotating_file_sink: failed renaming " + src + " to " + target);
|
throw spdlog_ex("rotating_file_sink: failed renaming " + src + " to " + target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_file_helper.reopen(true);
|
_file_helper.reopen(true);
|
||||||
}
|
}
|
||||||
std::string _base_filename;
|
std::string _base_filename;
|
||||||
std::string _extension;
|
std::string _extension;
|
||||||
std::size_t _max_size;
|
std::size_t _max_size;
|
||||||
std::size_t _max_files;
|
std::size_t _max_files;
|
||||||
std::size_t _current_size;
|
std::size_t _current_size;
|
||||||
details::file_helper _file_helper;
|
details::file_helper _file_helper;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
|
typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
|
||||||
@ -155,56 +155,56 @@ template<class Mutex>
|
|||||||
class daily_file_sink:public base_sink<Mutex>
|
class daily_file_sink:public base_sink<Mutex>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit daily_file_sink(const std::string& base_filename,
|
explicit daily_file_sink(const std::string& base_filename,
|
||||||
const std::string& extension,
|
const std::string& extension,
|
||||||
bool auto_flush=false):
|
bool auto_flush=false):
|
||||||
_base_filename(base_filename),
|
_base_filename(base_filename),
|
||||||
_extension(extension),
|
_extension(extension),
|
||||||
_midnight_tp (_calc_midnight_tp() ),
|
_midnight_tp (_calc_midnight_tp() ),
|
||||||
_file_helper(auto_flush)
|
_file_helper(auto_flush)
|
||||||
{
|
{
|
||||||
_file_helper.open(calc_filename(_base_filename, _extension));
|
_file_helper.open(calc_filename(_base_filename, _extension));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _sink_it(const details::log_msg& msg) override
|
void _sink_it(const details::log_msg& msg) override
|
||||||
{
|
{
|
||||||
if (std::chrono::system_clock::now() >= _midnight_tp)
|
if (std::chrono::system_clock::now() >= _midnight_tp)
|
||||||
{
|
{
|
||||||
_file_helper.close();
|
_file_helper.close();
|
||||||
_file_helper.open(calc_filename(_base_filename, _extension));
|
_file_helper.open(calc_filename(_base_filename, _extension));
|
||||||
_midnight_tp = _calc_midnight_tp();
|
_midnight_tp = _calc_midnight_tp();
|
||||||
}
|
}
|
||||||
_file_helper.write(msg);
|
_file_helper.write(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Return next midnight's time_point
|
// Return next midnight's time_point
|
||||||
static std::chrono::system_clock::time_point _calc_midnight_tp()
|
static std::chrono::system_clock::time_point _calc_midnight_tp()
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
auto now = system_clock::now();
|
auto now = system_clock::now();
|
||||||
time_t tnow = std::chrono::system_clock::to_time_t(now);
|
time_t tnow = std::chrono::system_clock::to_time_t(now);
|
||||||
tm date = spdlog::details::os::localtime(tnow);
|
tm date = spdlog::details::os::localtime(tnow);
|
||||||
date.tm_hour = date.tm_min = date.tm_sec = 0;
|
date.tm_hour = date.tm_min = date.tm_sec = 0;
|
||||||
auto midnight = std::chrono::system_clock::from_time_t(std::mktime(&date));
|
auto midnight = std::chrono::system_clock::from_time_t(std::mktime(&date));
|
||||||
return system_clock::time_point(midnight + hours(24));
|
return system_clock::time_point(midnight + hours(24));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create filename for the form basename.YYYY-MM-DD.extension
|
//Create filename for the form basename.YYYY-MM-DD.extension
|
||||||
static std::string calc_filename(const std::string& basename, const std::string& extension)
|
static std::string calc_filename(const std::string& basename, const std::string& extension)
|
||||||
{
|
{
|
||||||
std::tm tm = spdlog::details::os::localtime();
|
std::tm tm = spdlog::details::os::localtime();
|
||||||
details::fmt::MemoryWriter w;
|
details::fmt::MemoryWriter w;
|
||||||
w.write("{}.{:04d}-{:02d}-{:02d}.{}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, extension);
|
w.write("{}.{:04d}-{:02d}-{:02d}.{}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, extension);
|
||||||
return w.str();
|
return w.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string _base_filename;
|
std::string _base_filename;
|
||||||
std::string _extension;
|
std::string _extension;
|
||||||
std::chrono::system_clock::time_point _midnight_tp;
|
std::chrono::system_clock::time_point _midnight_tp;
|
||||||
details::file_helper _file_helper;
|
details::file_helper _file_helper;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,8 +37,8 @@ template <class Mutex>
|
|||||||
class null_sink : public base_sink < Mutex >
|
class null_sink : public base_sink < Mutex >
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
void _sink_it(const details::log_msg&) override
|
void _sink_it(const details::log_msg&) override
|
||||||
{}
|
{}
|
||||||
|
|
||||||
};
|
};
|
||||||
typedef null_sink<details::null_mutex> null_sink_st;
|
typedef null_sink<details::null_mutex> null_sink_st;
|
||||||
|
@ -39,17 +39,17 @@ template<class Mutex>
|
|||||||
class ostream_sink: public base_sink<Mutex>
|
class ostream_sink: public base_sink<Mutex>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ostream_sink(std::ostream& os) :_ostream(os) {}
|
explicit ostream_sink(std::ostream& os) :_ostream(os) {}
|
||||||
ostream_sink(const ostream_sink&) = delete;
|
ostream_sink(const ostream_sink&) = delete;
|
||||||
ostream_sink& operator=(const ostream_sink&) = delete;
|
ostream_sink& operator=(const ostream_sink&) = delete;
|
||||||
virtual ~ostream_sink() = default;
|
virtual ~ostream_sink() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _sink_it(const details::log_msg& msg) override
|
virtual void _sink_it(const details::log_msg& msg) override
|
||||||
{
|
{
|
||||||
_ostream.write(msg.formatted.data(), msg.formatted.size());
|
_ostream.write(msg.formatted.data(), msg.formatted.size());
|
||||||
}
|
}
|
||||||
std::ostream& _ostream;
|
std::ostream& _ostream;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ostream_sink<std::mutex> ostream_sink_mt;
|
typedef ostream_sink<std::mutex> ostream_sink_mt;
|
||||||
|
@ -33,8 +33,8 @@ namespace sinks
|
|||||||
class sink
|
class sink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~sink() {}
|
virtual ~sink() {}
|
||||||
virtual void log(const details::log_msg& msg) = 0;
|
virtual void log(const details::log_msg& msg) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ template <class Mutex>
|
|||||||
class stdout_sink : public ostream_sink<Mutex>
|
class stdout_sink : public ostream_sink<Mutex>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
stdout_sink() : ostream_sink<Mutex>(std::cout) {}
|
stdout_sink() : ostream_sink<Mutex>(std::cout) {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ template <class Mutex>
|
|||||||
class stderr_sink : public ostream_sink<Mutex>
|
class stderr_sink : public ostream_sink<Mutex>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
stderr_sink() : ostream_sink<Mutex>(std::cerr) {}
|
stderr_sink() : ostream_sink<Mutex>(std::cerr) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef stderr_sink<std::mutex> stderr_sink_mt;
|
typedef stderr_sink<std::mutex> stderr_sink_mt;
|
||||||
|
@ -47,50 +47,50 @@ class syslog_sink : public sink
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//
|
//
|
||||||
syslog_sink(const std::string& ident = "", int syslog_option=0, int syslog_facility=LOG_USER):
|
syslog_sink(const std::string& ident = "", int syslog_option=0, int syslog_facility=LOG_USER):
|
||||||
_ident(ident)
|
_ident(ident)
|
||||||
{
|
{
|
||||||
_priorities[static_cast<int>(level::trace)] = LOG_DEBUG;
|
_priorities[static_cast<int>(level::trace)] = LOG_DEBUG;
|
||||||
_priorities[static_cast<int>(level::debug)] = LOG_DEBUG;
|
_priorities[static_cast<int>(level::debug)] = LOG_DEBUG;
|
||||||
_priorities[static_cast<int>(level::info)] = LOG_INFO;
|
_priorities[static_cast<int>(level::info)] = LOG_INFO;
|
||||||
_priorities[static_cast<int>(level::notice)] = LOG_NOTICE;
|
_priorities[static_cast<int>(level::notice)] = LOG_NOTICE;
|
||||||
_priorities[static_cast<int>(level::warn)] = LOG_WARNING;
|
_priorities[static_cast<int>(level::warn)] = LOG_WARNING;
|
||||||
_priorities[static_cast<int>(level::err)] = LOG_ERR;
|
_priorities[static_cast<int>(level::err)] = LOG_ERR;
|
||||||
_priorities[static_cast<int>(level::critical)] = LOG_CRIT;
|
_priorities[static_cast<int>(level::critical)] = LOG_CRIT;
|
||||||
_priorities[static_cast<int>(level::alert)] = LOG_ALERT;
|
_priorities[static_cast<int>(level::alert)] = LOG_ALERT;
|
||||||
_priorities[static_cast<int>(level::emerg)] = LOG_EMERG;
|
_priorities[static_cast<int>(level::emerg)] = LOG_EMERG;
|
||||||
_priorities[static_cast<int>(level::off)] = LOG_INFO;
|
_priorities[static_cast<int>(level::off)] = LOG_INFO;
|
||||||
|
|
||||||
//set ident to be program name if empty
|
//set ident to be program name if empty
|
||||||
::openlog(_ident.empty()? nullptr:_ident.c_str(), syslog_option, syslog_facility);
|
::openlog(_ident.empty()? nullptr:_ident.c_str(), syslog_option, syslog_facility);
|
||||||
}
|
}
|
||||||
~syslog_sink()
|
~syslog_sink()
|
||||||
{
|
{
|
||||||
::closelog();
|
::closelog();
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog_sink(const syslog_sink&) = delete;
|
syslog_sink(const syslog_sink&) = delete;
|
||||||
syslog_sink& operator=(const syslog_sink&) = delete;
|
syslog_sink& operator=(const syslog_sink&) = delete;
|
||||||
|
|
||||||
void log(const details::log_msg &msg) override
|
void log(const details::log_msg &msg) override
|
||||||
{
|
{
|
||||||
::syslog(syslog_prio_from_level(msg), "%s", msg.formatted.str().c_str());
|
::syslog(syslog_prio_from_level(msg), "%s", msg.formatted.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<int, 10> _priorities;
|
std::array<int, 10> _priorities;
|
||||||
//must store the ident because the man says openlog might use the pointer as is and not a string copy
|
//must store the ident because the man says openlog might use the pointer as is and not a string copy
|
||||||
const std::string _ident;
|
const std::string _ident;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Simply maps spdlog's log level to syslog priority level.
|
// Simply maps spdlog's log level to syslog priority level.
|
||||||
//
|
//
|
||||||
int syslog_prio_from_level(const details::log_msg &msg) const
|
int syslog_prio_from_level(const details::log_msg &msg) const
|
||||||
{
|
{
|
||||||
return _priorities[static_cast<int>(msg.level)];
|
return _priorities[static_cast<int>(msg.level)];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user