clang-format

This commit is contained in:
gabime 2018-03-09 15:26:33 +02:00
parent 461b5ef28a
commit a2653d409f
66 changed files with 2330 additions and 2587 deletions

View File

@ -3,18 +3,18 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#include <atomic>
#include <thread>
#include <vector>
#include <atomic>
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/file.hpp>
namespace logging = boost::log;
namespace src = boost::log::sources;
@ -23,62 +23,49 @@ namespace keywords = boost::log::keywords;
void init()
{
logging::add_file_log
(
keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
keywords::auto_flush = false,
keywords::format = "[%TimeStamp%]: %Message%"
);
logging::add_file_log(keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
keywords::auto_flush = false, keywords::format = "[%TimeStamp%]: %Message%");
logging::core::get()->set_filter
(
logging::trivial::severity >= logging::trivial::info
);
logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::info);
}
using namespace std;
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
int thread_count = 10;
if(argc > 1)
if (argc > 1)
thread_count = atoi(argv[1]);
int howmany = 1000000;
init();
logging::add_common_attributes();
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;
for (int t = 0; t < thread_count; ++t)
{
threads.push_back(std::thread([&]()
{
threads.push_back(std::thread([&]() {
while (true)
{
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";
}
}));
}
for(auto &t:threads)
for (auto &t : threads)
{
t.join();
};
return 0;
}

View File

@ -3,13 +3,13 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/file.hpp>
namespace logging = boost::log;
namespace src = boost::log::sources;
@ -18,29 +18,21 @@ namespace keywords = boost::log::keywords;
void init()
{
logging::add_file_log
(
keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
keywords::auto_flush = false,
keywords::format = "[%TimeStamp%]: %Message%"
);
logging::add_file_log(keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
keywords::auto_flush = false, keywords::format = "[%TimeStamp%]: %Message%");
logging::core::get()->set_filter
(
logging::trivial::severity >= logging::trivial::info
);
logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::info);
}
int main(int argc, char* [])
int main(int argc, char *[])
{
int howmany = 1000000;
init();
logging::add_common_attributes();
using namespace logging::trivial;
src::severity_logger_mt< severity_level > lg;
for(int i = 0 ; i < howmany; ++i)
src::severity_logger_mt<severity_level> lg;
for (int i = 0; i < howmany; ++i)
BOOST_LOG_SEV(lg, info) << "boost message #" << i << ": This is some text for your pleasure";
return 0;

View File

@ -3,9 +3,9 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#include <atomic>
#include <thread>
#include <vector>
#include <atomic>
#define _ELPP_THREAD_SAFE
#include "easylogging++.h"
@ -13,11 +13,11 @@ _INITIALIZE_EASYLOGGINGPP
using namespace std;
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
int thread_count = 10;
if(argc > 1)
if (argc > 1)
thread_count = atoi(argv[1]);
int howmany = 1000000;
@ -26,24 +26,23 @@ int main(int argc, char* argv[])
el::Configurations conf("easyl.conf");
el::Loggers::reconfigureLogger("default", conf);
std::atomic<int > msg_counter {0};
std::atomic<int> msg_counter{0};
vector<thread> threads;
for (int t = 0; t < thread_count; ++t)
{
threads.push_back(std::thread([&]()
{
threads.push_back(std::thread([&]() {
while (true)
{
int counter = ++msg_counter;
if (counter > howmany) break;
if (counter > howmany)
break;
LOG(INFO) << "easylog message #" << counter << ": This is some text for your pleasure";
}
}));
}
for(auto &t:threads)
for (auto &t : threads)
{
t.join();
};

View File

@ -3,12 +3,11 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#include "easylogging++.h"
_INITIALIZE_EASYLOGGINGPP
int main(int, char* [])
int main(int, char *[])
{
int howmany = 1000000;
@ -16,7 +15,7 @@ int main(int, char* [])
el::Configurations conf("easyl.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";
return 0;
}

View File

@ -3,57 +3,55 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
#include <iostream>
#include <chrono>
#include "g2logworker.h"
#include "g2log.h"
#include "g2logworker.h"
using namespace std;
template<typename T> std::string format(const T& value);
template <typename T> std::string format(const T &value);
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
using namespace std::chrono;
using clock=steady_clock;
using clock = steady_clock;
int thread_count = 10;
if(argc > 1)
if (argc > 1)
thread_count = atoi(argv[1]);
int howmany = 1000000;
g2LogWorker g2log(argv[0], "logs");
g2::initializeLogging(&g2log);
std::atomic<int > msg_counter {0};
std::atomic<int> msg_counter{0};
vector<thread> threads;
auto start = clock::now();
for (int t = 0; t < thread_count; ++t)
{
threads.push_back(std::thread([&]()
{
threads.push_back(std::thread([&]() {
while (true)
{
int counter = ++msg_counter;
if (counter > howmany) break;
if (counter > howmany)
break;
LOG(INFO) << "g2log message #" << counter << ": This is some text for your pleasure";
}
}));
}
for(auto &t:threads)
for (auto &t : threads)
{
t.join();
};
duration<float> delta = clock::now() - start;
float deltaf = delta.count();
auto rate = howmany/deltaf;
auto rate = howmany / deltaf;
cout << "Total: " << howmany << std::endl;
cout << "Threads: " << thread_count << std::endl;

View File

@ -3,19 +3,19 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#include <atomic>
#include <thread>
#include <vector>
#include <atomic>
#include "glog/logging.h"
using namespace std;
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
int thread_count = 10;
if(argc > 1)
if (argc > 1)
thread_count = atoi(argv[1]);
int howmany = 1000000;
@ -24,24 +24,23 @@ int main(int argc, char* argv[])
FLAGS_log_dir = "logs";
google::InitGoogleLogging(argv[0]);
std::atomic<int > msg_counter {0};
std::atomic<int> msg_counter{0};
vector<thread> threads;
for (int t = 0; t < thread_count; ++t)
{
threads.push_back(std::thread([&]()
{
threads.push_back(std::thread([&]() {
while (true)
{
int counter = ++msg_counter;
if (counter > howmany) break;
if (counter > howmany)
break;
LOG(INFO) << "glog message #" << counter << ": This is some text for your pleasure";
}
}));
}
for(auto &t:threads)
for (auto &t : threads)
{
t.join();
};

View File

@ -5,16 +5,14 @@
#include "glog/logging.h"
int main(int, char* argv[])
int main(int, char *argv[])
{
int howmany = 1000000;
FLAGS_logtostderr = 0;
FLAGS_log_dir = "logs";
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";
return 0;

View File

@ -9,29 +9,26 @@ void CrusherLoop()
while (true)
{
LOGF(INFO, "Some text to crush you machine. thread:");
if(++counter % 1000000 == 0)
if (++counter % 1000000 == 0)
{
std::cout << "Wrote " << counter << " entries" << std::endl;
}
}
}
int main(int argc, char** argv)
int main(int argc, char **argv)
{
std::cout << "WARNING: This test will exaust all your machine memory and will crush it!" << std::endl;
std::cout << "Are you sure you want to continue ? " << std::endl;
char c;
std::cin >> c;
if (toupper( c ) != 'Y')
if (toupper(c) != 'Y')
return 0;
auto worker = g3::LogWorker::createLogWorker();
auto handle= worker->addDefaultLogger(argv[0], "g3log.txt");
auto handle = worker->addDefaultLogger(argv[0], "g3log.txt");
g3::initializeLogging(worker.get());
CrusherLoop();
return 0;
}

View File

@ -1,32 +1,26 @@
#include <thread>
#include <vector>
#include <atomic>
#include <iostream>
#include <chrono>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstdio>
#include <map>
#include <numeric>
#include <functional>
#include <thread>
#include "utils.h"
#include <algorithm>
#include <atomic>
#include <chrono>
#include <cstdio>
#include <fstream>
#include <functional>
#include <g3log/g3log.hpp>
#include <g3log/logworker.hpp>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <sstream>
#include <thread>
#include <vector>
namespace
{
namespace {
const uint64_t g_iterations = 1000000;
std::atomic<size_t> g_counter = {0};
void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t>& result)
void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t> &result)
{
while (true)
@ -45,14 +39,12 @@ void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t>& result)
}
}
void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result, size_t total_us)
void PrintResults(const std::map<size_t, std::vector<uint64_t>> &threads_result, size_t total_us)
{
std::vector<uint64_t> all_measurements;
all_measurements.reserve(g_iterations);
for (auto& t_result : threads_result)
for (auto &t_result : threads_result)
{
all_measurements.insert(all_measurements.end(), t_result.second.begin(), t_result.second.end());
}
@ -62,13 +54,12 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result,
// calc avg
auto total = accumulate(begin(all_measurements), end(all_measurements), 0, std::plus<uint64_t>());
auto avg = double(total)/all_measurements.size();
std::cout << "[g3log] worst: " << std::setw(10) << std::right << worst << "\tAvg: " << avg << "\tTotal: " << utils::format(total_us) << " us" << std::endl;
auto avg = double(total) / all_measurements.size();
std::cout << "[g3log] worst: " << std::setw(10) << std::right << worst << "\tAvg: " << avg << "\tTotal: " << utils::format(total_us)
<< " us" << std::endl;
}
}// anonymous
} // namespace
// The purpose of this test is NOT to see how fast
// each thread can possibly write. It is to see what
@ -78,9 +69,9 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result,
// an atomic counter is used to give each thread what
// it is to write next. The overhead of atomic
// synchronization between the threads are not counted in the worst case latency
int main(int argc, char** argv)
int main(int argc, char **argv)
{
size_t number_of_threads {0};
size_t number_of_threads{0};
if (argc == 2)
{
number_of_threads = atoi(argv[1]);
@ -91,7 +82,6 @@ int main(int argc, char** argv)
return 1;
}
std::vector<std::thread> threads(number_of_threads);
std::map<size_t, std::vector<uint64_t>> threads_result;
@ -102,12 +92,12 @@ int main(int argc, char** argv)
threads_result[idx].reserve(g_iterations);
}
const std::string g_path = "./" ;
const std::string g_prefix_log_name = "g3log-performance-";
const std::string g_measurement_dump = g_path + g_prefix_log_name + "_RESULT.txt";
const std::string g_path = "./";
const std::string g_prefix_log_name = "g3log-performance-";
const std::string g_measurement_dump = g_path + g_prefix_log_name + "_RESULT.txt";
auto worker = g3::LogWorker::createLogWorker();
auto handle= worker->addDefaultLogger(argv[0], "g3log.txt");
auto handle = worker->addDefaultLogger(argv[0], "g3log.txt");
g3::initializeLogging(worker.get());
auto start_time_application_total = std::chrono::high_resolution_clock::now();
@ -121,9 +111,8 @@ int main(int argc, char** argv)
}
auto stop_time_application_total = std::chrono::high_resolution_clock::now();
uint64_t total_time_in_us = std::chrono::duration_cast<std::chrono::microseconds>(stop_time_application_total - start_time_application_total).count();
uint64_t total_time_in_us =
std::chrono::duration_cast<std::chrono::microseconds>(stop_time_application_total - start_time_application_total).count();
PrintResults(threads_result, total_time_in_us);
return 0;
}

View File

@ -1,31 +1,26 @@
#include <thread>
#include <vector>
#include <atomic>
#include <iostream>
#include <chrono>
#include "utils.h"
#include <algorithm>
#include <iostream>
#include <atomic>
#include <chrono>
#include <cstdio>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <functional>
#include "utils.h"
#include <thread>
#include <vector>
#include "spdlog/spdlog.h"
namespace spd = spdlog;
namespace
{
namespace {
const uint64_t g_iterations = 1000000;
std::atomic<size_t> g_counter = {0};
void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t>& result)
void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t> &result)
{
auto logger = spd::get("file_logger");
while (true)
@ -44,13 +39,12 @@ void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t>& result)
}
}
void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result, size_t total_us)
void PrintResults(const std::map<size_t, std::vector<uint64_t>> &threads_result, size_t total_us)
{
std::vector<uint64_t> all_measurements;
all_measurements.reserve(g_iterations);
for (auto& t_result : threads_result)
for (auto &t_result : threads_result)
{
all_measurements.insert(all_measurements.end(), t_result.second.begin(), t_result.second.end());
}
@ -60,13 +54,12 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result,
// calc avg
auto total = accumulate(begin(all_measurements), end(all_measurements), 0, std::plus<uint64_t>());
auto avg = double(total)/all_measurements.size();
std::cout << "[spdlog] worst: " << std::setw(10) << std::right << worst << "\tAvg: " << avg << "\tTotal: " << utils::format(total_us) << " us" << std::endl;
auto avg = double(total) / all_measurements.size();
std::cout << "[spdlog] worst: " << std::setw(10) << std::right << worst << "\tAvg: " << avg << "\tTotal: " << utils::format(total_us)
<< " us" << std::endl;
}
}// anonymous
} // namespace
// The purpose of this test is NOT to see how fast
// each thread can possibly write. It is to see what
@ -76,9 +69,9 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result,
// an atomic counter is used to give each thread what
// it is to write next. The overhead of atomic
// synchronization between the threads are not counted in the worst case latency
int main(int argc, char** argv)
int main(int argc, char **argv)
{
size_t number_of_threads {0};
size_t number_of_threads{0};
if (argc == 2)
{
number_of_threads = atoi(argv[1]);
@ -89,7 +82,6 @@ int main(int argc, char** argv)
return 1;
}
std::vector<std::thread> threads(number_of_threads);
std::map<size_t, std::vector<uint64_t>> threads_result;
@ -104,8 +96,8 @@ int main(int argc, char** argv)
spdlog::set_async_mode(queue_size);
auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "spdlog.log", true);
//force flush on every call to compare with g3log
auto s = (spd::sinks::simple_file_sink_mt*)logger->sinks()[0].get();
// force flush on every call to compare with g3log
auto s = (spd::sinks::simple_file_sink_mt *)logger->sinks()[0].get();
s->set_force_flush(true);
auto start_time_application_total = std::chrono::high_resolution_clock::now();
@ -119,10 +111,9 @@ int main(int argc, char** argv)
}
auto stop_time_application_total = std::chrono::high_resolution_clock::now();
uint64_t total_time_in_us = std::chrono::duration_cast<std::chrono::microseconds>(stop_time_application_total - start_time_application_total).count();
uint64_t total_time_in_us =
std::chrono::duration_cast<std::chrono::microseconds>(stop_time_application_total - start_time_application_total).count();
PrintResults(threads_result, total_time_in_us);
return 0;
}

View File

@ -5,15 +5,13 @@
#pragma once
#include <sstream>
#include <iomanip>
#include <locale>
#include <sstream>
namespace utils
{
namespace utils {
template<typename T>
inline std::string format(const T& value)
template <typename T> inline std::string format(const T &value)
{
static std::locale loc("");
std::stringstream ss;
@ -22,8 +20,7 @@ inline std::string format(const T& value)
return ss.str();
}
template<>
inline std::string format(const double & value)
template <> inline std::string format(const double &value)
{
static std::locale loc("");
std::stringstream ss;
@ -32,4 +29,4 @@ inline std::string format(const double & value)
return ss.str();
}
}
} // namespace utils

View File

@ -3,25 +3,25 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#include <thread>
#include <vector>
#include "spdlog/spdlog.h"
#include <atomic>
#include <iostream>
#include <chrono>
#include <cstdlib>
#include "spdlog/spdlog.h"
#include <iostream>
#include <thread>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
using namespace std::chrono;
using clock=steady_clock;
using clock = steady_clock;
namespace spd = spdlog;
int thread_count = 10;
if(argc > 1)
if (argc > 1)
thread_count = ::atoi(argv[1]);
int howmany = 1000000;
@ -29,31 +29,30 @@ int main(int argc, char* argv[])
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");
std::atomic<int > msg_counter {0};
std::atomic<int> msg_counter{0};
vector<thread> threads;
auto start = clock::now();
for (int t = 0; t < thread_count; ++t)
{
threads.push_back(std::thread([&]()
{
threads.push_back(std::thread([&]() {
while (true)
{
int counter = ++msg_counter;
if (counter > howmany) break;
if (counter > howmany)
break;
logger->info("spdlog message #{}: This is some text for your pleasure", counter);
}
}));
}
for(auto &t:threads)
for (auto &t : threads)
{
t.join();
};
duration<float> delta = clock::now() - start;
float deltaf = delta.count();
auto rate = howmany/deltaf;
auto rate = howmany / deltaf;
cout << "Total: " << howmany << std::endl;
cout << "Threads: " << thread_count << std::endl;

View File

@ -3,20 +3,19 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#include <thread>
#include <vector>
#include "spdlog/spdlog.h"
#include <atomic>
#include <cstdlib>
#include "spdlog/spdlog.h"
#include <thread>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
int thread_count = 10;
if(argc > 1)
if (argc > 1)
thread_count = std::atoi(argv[1]);
int howmany = 1000000;
@ -27,29 +26,26 @@ int main(int argc, char* argv[])
logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
std::atomic<int > msg_counter {0};
std::atomic<int> msg_counter{0};
std::vector<thread> threads;
for (int t = 0; t < thread_count; ++t)
{
threads.push_back(std::thread([&]()
{
threads.push_back(std::thread([&]() {
while (true)
{
int counter = ++msg_counter;
if (counter > howmany) break;
if (counter > howmany)
break;
logger->info("spdlog message #{}: This is some text for your pleasure", counter);
}
}));
}
for(auto &t:threads)
for (auto &t : threads)
{
t.join();
};
return 0;
}

View File

@ -5,16 +5,15 @@
#include "spdlog/spdlog.h"
int main(int, char* [])
int main(int, char *[])
{
int howmany = 1000000;
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);
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 #{} : This is some text for your pleasure", i);
return 0;
}

View File

@ -6,17 +6,16 @@
//
// bench.cpp : spdlog benchmarks
//
#include "spdlog/async_logger.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/spdlog.h"
#include "utils.h"
#include <atomic>
#include <cstdlib> // EXIT_FAILURE
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include "spdlog/spdlog.h"
#include "spdlog/async_logger.h"
#include "spdlog/sinks/null_sink.h"
#include "utils.h"
using namespace std;
using namespace std::chrono;
@ -24,11 +23,9 @@ using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;
size_t bench_as(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
int queue_size = 1048576;
@ -39,14 +36,13 @@ int main(int argc, char* argv[])
try
{
if(argc > 1)
if (argc > 1)
howmany = atoi(argv[1]);
if (argc > 2)
threads = atoi(argv[2]);
threads = atoi(argv[2]);
if (argc > 3)
queue_size = atoi(argv[3]);
cout << "\n*******************************************************************************\n";
cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " messages " << endl;
cout << "*******************************************************************************\n";
@ -55,16 +51,15 @@ int main(int argc, char* argv[])
size_t total_rate = 0;
for(int i = 0; i < iters; ++i)
for (int i = 0; i < iters; ++i)
{
//auto as = spdlog::daily_logger_st("as", "logs/daily_async");
// auto as = spdlog::daily_logger_st("as", "logs/daily_async");
auto as = spdlog::create<null_sink_st>("async(null-sink)");
total_rate+= bench_as(howmany, as, threads);
total_rate += bench_as(howmany, as, threads);
spdlog::drop("async(null-sink)");
}
std::cout << endl;
std::cout << "Avg rate: " << format(total_rate/iters) << "/sec" <<std::endl;
std::cout << "Avg rate: " << format(total_rate / iters) << "/sec" << std::endl;
}
catch (std::exception &ex)
{
@ -75,37 +70,33 @@ int main(int argc, char* argv[])
return EXIT_SUCCESS;
}
//return rate/sec
// return rate/sec
size_t bench_as(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{
cout << log->name() << "...\t\t" << flush;
std::atomic<int > msg_counter {0};
std::atomic<int> msg_counter{0};
vector<thread> threads;
auto start = system_clock::now();
for (int t = 0; t < thread_count; ++t)
{
threads.push_back(std::thread([&]()
{
for(;;)
threads.push_back(std::thread([&]() {
for (;;)
{
int counter = ++msg_counter;
if (counter > howmany) break;
if (counter > howmany)
break;
log->info("Hello logger: msg number {}", counter);
}
}));
}
for(auto &t:threads)
for (auto &t : threads)
{
t.join();
};
auto delta = system_clock::now() - start;
auto delta_d = duration_cast<duration<double>> (delta).count();
auto delta_d = duration_cast<duration<double>>(delta).count();
auto per_sec = size_t(howmany / delta_d);
cout << format(per_sec) << "/sec" << endl;
return per_sec;

View File

@ -5,15 +5,13 @@
#pragma once
#include <sstream>
#include <iomanip>
#include <locale>
#include <sstream>
namespace utils
{
namespace utils {
template<typename T>
inline std::string format(const T& value)
template <typename T> inline std::string format(const T &value)
{
static std::locale loc("");
std::stringstream ss;
@ -22,8 +20,7 @@ inline std::string format(const T& value)
return ss.str();
}
template<>
inline std::string format(const double & value)
template <> inline std::string format(const double &value)
{
static std::locale loc("");
std::stringstream ss;
@ -32,4 +29,4 @@ inline std::string format(const double & value)
return ss.str();
}
}
} // namespace utils

View File

@ -6,18 +6,17 @@
//
// bench.cpp : spdlog benchmarks
//
#include "spdlog/async_logger.h"
#include "spdlog/sinks/file_sinks.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/spdlog.h"
#include "utils.h"
#include <atomic>
#include <cstdlib> // EXIT_FAILURE
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include "spdlog/spdlog.h"
#include "spdlog/async_logger.h"
#include "spdlog/sinks/file_sinks.h"
#include "spdlog/sinks/null_sink.h"
#include "utils.h"
using namespace std;
using namespace std::chrono;
@ -25,11 +24,10 @@ using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;
void bench(int howmany, std::shared_ptr<spdlog::logger> log);
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 queue_size = 1048576;
@ -41,16 +39,15 @@ int main(int argc, char* argv[])
try
{
if(argc > 1)
if (argc > 1)
howmany = atoi(argv[1]);
if (argc > 2)
threads = atoi(argv[2]);
threads = atoi(argv[2]);
if (argc > 3)
queue_size = atoi(argv[3]);
cout << "*******************************************************************************\n";
cout << "Single thread, " << format(howmany) << " iterations" << endl;
cout << "Single thread, " << format(howmany) << " iterations" << endl;
cout << "*******************************************************************************\n";
auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files);
@ -60,13 +57,12 @@ int main(int argc, char* argv[])
bench(howmany, spdlog::create<null_sink_st>("null_st"));
cout << "\n*******************************************************************************\n";
cout << threads << " threads sharing same logger, " << format(howmany) << " iterations" << endl;
cout << threads << " threads sharing same logger, " << format(howmany) << " iterations" << endl;
cout << "*******************************************************************************\n";
auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files);
bench_mt(howmany, rotating_mt, threads);
auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log");
bench_mt(howmany, daily_mt, threads);
bench(howmany, spdlog::create<null_sink_st>("null_mt"));
@ -75,10 +71,9 @@ int main(int argc, char* argv[])
cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations " << endl;
cout << "*******************************************************************************\n";
spdlog::set_async_mode(queue_size);
for(int i = 0; i < 3; ++i)
for (int i = 0; i < 3; ++i)
{
auto as = spdlog::daily_logger_st("as", "logs/daily_async.log");
bench_mt(howmany, as, threads);
@ -94,7 +89,6 @@ int main(int argc, char* argv[])
return EXIT_SUCCESS;
}
void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{
cout << log->name() << "...\t\t" << flush;
@ -104,41 +98,37 @@ void bench(int howmany, std::shared_ptr<spdlog::logger> log)
log->info("Hello logger: msg number {}", i);
}
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;
}
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{
cout << log->name() << "...\t\t" << flush;
std::atomic<int > msg_counter {0};
std::atomic<int> msg_counter{0};
vector<thread> threads;
auto start = system_clock::now();
for (int t = 0; t < thread_count; ++t)
{
threads.push_back(std::thread([&]()
{
for(;;)
threads.push_back(std::thread([&]() {
for (;;)
{
int counter = ++msg_counter;
if (counter > howmany) break;
if (counter > howmany)
break;
log->info("Hello logger: msg number {}", counter);
}
}));
}
for(auto &t:threads)
for (auto &t : threads)
{
t.join();
};
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;
}

View File

@ -22,7 +22,7 @@ void user_defined_example();
void err_handler_example();
namespace spd = spdlog;
int main(int, char*[])
int main(int, char *[])
{
try
{
@ -31,7 +31,6 @@ int main(int, char*[])
console->info("Welcome to spdlog!");
console->error("Some error message with arg{}..", 1);
// Formatting examples
console->warn("Easy padding in numbers like {:08d}", 12);
console->critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
@ -41,7 +40,6 @@ int main(int, char*[])
spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
// Create basic file logger (not rotated)
auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic-log.txt");
my_logger->info("Some log message");
@ -49,7 +47,7 @@ int main(int, char*[])
// Create a file rotating logger with 5mb size max and 3 rotated files
auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3);
for (int i = 0; i < 10; ++i)
rotating_logger->info("{} * {} equals {:>10}", i, i, i*i);
rotating_logger->info("{} * {} equals {:>10}", i, i, i * i);
// Create a daily logger - a new file is created every day on 2:30am
auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
@ -61,9 +59,8 @@ int main(int, char*[])
spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
rotating_logger->info("This is another message with custom format");
// Runtime log levels
spd::set_level(spd::level::info); //Set global log level to info
spd::set_level(spd::level::info); // Set global log level to info
console->debug("This message should not be displayed!");
console->set_level(spd::level::debug); // Set specific logger's log level
console->debug("This message should be displayed..");
@ -73,7 +70,6 @@ int main(int, char*[])
SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
// Asynchronous logging is very fast..
// Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
async_example();
@ -91,16 +87,13 @@ int main(int, char*[])
err_handler_example();
// Apply a function on all registered loggers
spd::apply_all([&](std::shared_ptr<spdlog::logger> l)
{
l->info("End of example.");
});
spd::apply_all([&](std::shared_ptr<spdlog::logger> l) { l->info("End of example."); });
// Release and close all loggers
spdlog::drop_all();
}
// Exceptions will only be thrown upon failed logger or sink construction (not during logging)
catch (const spd::spdlog_ex& ex)
catch (const spd::spdlog_ex &ex)
{
std::cout << "Log init failed: " << ex.what() << std::endl;
return 1;
@ -109,14 +102,14 @@ int main(int, char*[])
void async_example()
{
size_t q_size = 4096; //queue size must be power of 2
size_t q_size = 4096; // queue size must be power of 2
spdlog::set_async_mode(q_size);
auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
for (int i = 0; i < 100; ++i)
async_file->info("Async message #{}", i);
}
//syslog example (linux/osx/freebsd)
// syslog example (linux/osx/freebsd)
void syslog_example()
{
#ifdef SPDLOG_ENABLE_SYSLOG
@ -140,28 +133,24 @@ void android_example()
struct my_type
{
int i;
template<typename OStream>
friend OStream& operator<<(OStream& os, const my_type &c)
template <typename OStream> friend OStream &operator<<(OStream &os, const my_type &c)
{
return os << "[my_type i="<<c.i << "]";
return os << "[my_type i=" << c.i << "]";
}
};
#include "spdlog/fmt/ostr.h" // must be included
void user_defined_example()
{
spd::get("console")->info("user defined type: {}", my_type { 14 });
spd::get("console")->info("user defined type: {}", my_type{14});
}
//
//custom error handler
// custom error handler
//
void err_handler_example()
{
//can be set globaly or per logger(logger->set_error_handler(..))
spdlog::set_error_handler([](const std::string& msg)
{
std::cerr << "my err handler: " << msg << std::endl;
});
// can be set globaly or per logger(logger->set_error_handler(..))
spdlog::set_error_handler([](const std::string &msg) { std::cerr << "my err handler: " << msg << std::endl; });
spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
}

View File

@ -1 +0,0 @@
../example.cpp

156
example/jni/example.cpp Normal file
View File

@ -0,0 +1,156 @@
//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
//
// spdlog usage example
//
//
#define SPDLOG_TRACE_ON
#define SPDLOG_DEBUG_ON
#include "spdlog/spdlog.h"
#include <iostream>
#include <memory>
void async_example();
void syslog_example();
void android_example();
void user_defined_example();
void err_handler_example();
namespace spd = spdlog;
int main(int, char *[])
{
try
{
// Console logger with color
auto console = spd::stdout_color_mt("console");
console->info("Welcome to spdlog!");
console->error("Some error message with arg{}..", 1);
// Formatting examples
console->warn("Easy padding in numbers like {:08d}", 12);
console->critical("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("Positional args are {1} {0}..", "too", "supported");
console->info("{:<30}", "left aligned");
spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
// Create basic file logger (not rotated)
auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic-log.txt");
my_logger->info("Some log message");
// Create a file rotating logger with 5mb size max and 3 rotated files
auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3);
for (int i = 0; i < 10; ++i)
rotating_logger->info("{} * {} equals {:>10}", i, i, i * i);
// Create a daily logger - a new file is created every day on 2:30am
auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
// trigger flush if the log severity is error or higher
daily_logger->flush_on(spd::level::err);
daily_logger->info(123.44);
// Customize msg format for all messages
spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
rotating_logger->info("This is another message with custom format");
// Runtime log levels
spd::set_level(spd::level::info); // Set global log level to info
console->debug("This message should not be displayed!");
console->set_level(spd::level::debug); // Set specific logger's log level
console->debug("This message should be displayed..");
// Compile time log levels
// define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON
SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
// Asynchronous logging is very fast..
// Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
async_example();
// syslog example. linux/osx only
syslog_example();
// android example. compile with NDK
android_example();
// Log user-defined types example
user_defined_example();
// Change default log error handler
err_handler_example();
// Apply a function on all registered loggers
spd::apply_all([&](std::shared_ptr<spdlog::logger> l) { l->info("End of example."); });
// Release and close all loggers
spdlog::drop_all();
}
// Exceptions will only be thrown upon failed logger or sink construction (not during logging)
catch (const spd::spdlog_ex &ex)
{
std::cout << "Log init failed: " << ex.what() << std::endl;
return 1;
}
}
void async_example()
{
size_t q_size = 4096; // queue size must be power of 2
spdlog::set_async_mode(q_size);
auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
for (int i = 0; i < 100; ++i)
async_file->info("Async message #{}", i);
}
// syslog example (linux/osx/freebsd)
void syslog_example()
{
#ifdef SPDLOG_ENABLE_SYSLOG
std::string ident = "spdlog-example";
auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID);
syslog_logger->warn("This is warning that will end up in syslog.");
#endif
}
// Android example
void android_example()
{
#if defined(__ANDROID__)
std::string tag = "spdlog-android";
auto android_logger = spd::android_logger("android", tag);
android_logger->critical("Use \"adb shell logcat\" to view this message.");
#endif
}
// user defined types logging by implementing operator<<
struct my_type
{
int i;
template <typename OStream> friend OStream &operator<<(OStream &os, const my_type &c)
{
return os << "[my_type i=" << c.i << "]";
}
};
#include "spdlog/fmt/ostr.h" // must be included
void user_defined_example()
{
spd::get("console")->info("user defined type: {}", my_type{14});
}
//
// custom error handler
//
void err_handler_example()
{
// can be set globaly or per logger(logger->set_error_handler(..))
spdlog::set_error_handler([](const std::string &msg) { std::cerr << "my err handler: " << msg << std::endl; });
spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
}

View File

@ -4,7 +4,7 @@
#include <memory>
namespace spd = spdlog;
int main(int, char*[])
int main(int, char *[])
{
bool enable_debug = true;
try
@ -13,24 +13,24 @@ int main(int, char*[])
// This means that the same log_msg is forwarded to multiple sinks;
// Each sink can have it's own log level and a message will be logged.
std::vector<spdlog::sink_ptr> sinks;
sinks.push_back( std::make_shared<spdlog::sinks::stdout_sink_mt>() );
sinks.push_back( std::make_shared<spdlog::sinks::simple_file_sink_mt>("./log_regular_file.txt") );
sinks.push_back( std::make_shared<spdlog::sinks::simple_file_sink_mt>("./log_debug_file.txt") );
sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_mt>());
sinks.push_back(std::make_shared<spdlog::sinks::simple_file_sink_mt>("./log_regular_file.txt"));
sinks.push_back(std::make_shared<spdlog::sinks::simple_file_sink_mt>("./log_debug_file.txt"));
spdlog::logger console_multisink("multisink", sinks.begin(), sinks.end() );
console_multisink.set_level( spdlog::level::warn);
spdlog::logger console_multisink("multisink", sinks.begin(), sinks.end());
console_multisink.set_level(spdlog::level::warn);
sinks[0]->set_level( spdlog::level::trace); // console. Allow everything. Default value
sinks[1]->set_level( spdlog::level::trace); // regular file. Allow everything. Default value
sinks[2]->set_level( spdlog::level::off); // regular file. Ignore everything.
sinks[0]->set_level(spdlog::level::trace); // console. Allow everything. Default value
sinks[1]->set_level(spdlog::level::trace); // regular file. Allow everything. Default value
sinks[2]->set_level(spdlog::level::off); // regular file. Ignore everything.
console_multisink.warn("warn: will print only on console and regular file");
if( enable_debug )
if (enable_debug)
{
console_multisink.set_level( spdlog::level::debug); // level of the logger
sinks[1]->set_level( spdlog::level::debug); // regular file
sinks[2]->set_level( spdlog::level::debug); // debug file
console_multisink.set_level(spdlog::level::debug); // level of the logger
sinks[1]->set_level(spdlog::level::debug); // regular file
sinks[2]->set_level(spdlog::level::debug); // debug file
}
console_multisink.debug("Debug: you should see this on console and both files");
@ -38,10 +38,9 @@ int main(int, char*[])
spdlog::drop_all();
}
// Exceptions will only be thrown upon failed logger or sink construction (not during logging)
catch (const spd::spdlog_ex& ex)
catch (const spd::spdlog_ex &ex)
{
std::cout << "Log init failed: " << ex.what() << std::endl;
return 1;
}
}

View File

@ -5,15 +5,13 @@
#pragma once
#include <sstream>
#include <iomanip>
#include <locale>
#include <sstream>
namespace utils
{
namespace utils {
template<typename T>
inline std::string format(const T& value)
template <typename T> inline std::string format(const T &value)
{
static std::locale loc("");
std::stringstream ss;
@ -22,8 +20,7 @@ inline std::string format(const T& value)
return ss.str();
}
template<>
inline std::string format(const double & value)
template <> inline std::string format(const double &value)
{
static std::locale loc("");
std::stringstream ss;
@ -32,4 +29,4 @@ inline std::string format(const double & value)
return ss.str();
}
}
} // namespace utils

View File

@ -20,48 +20,39 @@
#include <chrono>
#include <functional>
#include <string>
#include <memory>
#include <string>
namespace spdlog
{
namespace spdlog {
namespace details
{
namespace details {
class async_log_helper;
}
class async_logger SPDLOG_FINAL : public logger
{
public:
template<class It>
async_logger(const std::string& logger_name,
const It& begin,
const It& end,
size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()>& worker_warmup_cb = nullptr,
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()>& worker_teardown_cb = nullptr);
template <class It>
async_logger(const std::string &logger_name, const It &begin, const It &end, size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
async_logger(const std::string& logger_name,
sinks_init_list sinks,
size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()>& worker_warmup_cb = nullptr,
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()>& worker_teardown_cb = nullptr);
async_logger(const std::string &logger_name, sinks_init_list sinks, size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
async_logger(const std::string& logger_name,
sink_ptr single_sink,
size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()>& worker_warmup_cb = nullptr,
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()>& worker_teardown_cb = nullptr);
async_logger(const std::string &logger_name, sink_ptr single_sink, size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
//Wait for the queue to be empty, and flush synchronously
//Warning: this can potentially last forever as we wait it to complete
// Wait for the queue to be empty, and flush synchronously
// Warning: this can potentially last forever as we wait it to complete
void flush() override;
// Error handler
@ -69,13 +60,13 @@ public:
log_err_handler error_handler() override;
protected:
void _sink_it(details::log_msg& msg) override;
void _sink_it(details::log_msg &msg) override;
void _set_formatter(spdlog::formatter_ptr msg_formatter) override;
void _set_pattern(const std::string& pattern, pattern_time_type pattern_time) override;
void _set_pattern(const std::string &pattern, pattern_time_type pattern_time) override;
private:
std::unique_ptr<details::async_log_helper> _async_log_helper;
};
}
} // namespace spdlog
#include "details/async_logger_impl.h"

View File

@ -13,11 +13,11 @@
#pragma once
#include "../common.h"
#include "../sinks/sink.h"
#include "../details/mpmc_bounded_q.h"
#include "../details/log_msg.h"
#include "../details/mpmc_bounded_q.h"
#include "../details/os.h"
#include "../formatter.h"
#include "../sinks/sink.h"
#include <chrono>
#include <exception>
@ -28,10 +28,7 @@
#include <utility>
#include <vector>
namespace spdlog
{
namespace details
{
namespace spdlog { namespace details {
class async_log_helper
{
@ -57,24 +54,25 @@ class async_log_helper
async_msg() = default;
~async_msg() = default;
explicit async_msg(async_msg_type m_type) :
level(level::info),
thread_id(0),
msg_type(m_type),
msg_id(0)
{}
explicit async_msg(async_msg_type m_type)
: level(level::info)
, thread_id(0)
, msg_type(m_type)
, msg_id(0)
{
}
async_msg(async_msg&& other) SPDLOG_NOEXCEPT :
logger_name(std::move(other.logger_name)),
level(std::move(other.level)),
time(std::move(other.time)),
thread_id(other.thread_id),
txt(std::move(other.txt)),
msg_type(std::move(other.msg_type)),
msg_id(other.msg_id)
{}
async_msg(async_msg &&other) SPDLOG_NOEXCEPT : logger_name(std::move(other.logger_name)),
level(std::move(other.level)),
time(std::move(other.time)),
thread_id(other.thread_id),
txt(std::move(other.txt)),
msg_type(std::move(other.msg_type)),
msg_id(other.msg_id)
{
}
async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT
async_msg &operator=(async_msg &&other) SPDLOG_NOEXCEPT
{
logger_name = std::move(other.logger_name);
level = other.level;
@ -87,17 +85,17 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT :
}
// never copy or assign. should only be moved..
async_msg(const async_msg&) = delete;
async_msg& operator=(const async_msg& other) = delete;
async_msg(const async_msg &) = delete;
async_msg &operator=(const async_msg &other) = delete;
// construct from log_msg
explicit async_msg(const details::log_msg& m):
level(m.level),
time(m.time),
thread_id(m.thread_id),
txt(m.raw.data(), m.raw.size()),
msg_type(async_msg_type::log),
msg_id(m.msg_id)
explicit async_msg(const details::log_msg &m)
: level(m.level)
, time(m.time)
, thread_id(m.thread_id)
, txt(m.raw.data(), m.raw.size())
, msg_type(async_msg_type::log)
, msg_id(m.msg_id)
{
#ifndef SPDLOG_NO_NAME
logger_name = *m.logger_name;
@ -122,22 +120,18 @@ public:
using clock = std::chrono::steady_clock;
async_log_helper(formatter_ptr formatter,
std::vector<sink_ptr> sinks,
size_t queue_size,
const log_err_handler err_handler,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
std::function<void()> worker_warmup_cb = nullptr,
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
std::function<void()> worker_teardown_cb = nullptr);
async_log_helper(formatter_ptr formatter, std::vector<sink_ptr> sinks, size_t queue_size, const log_err_handler err_handler,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, std::function<void()> worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
std::function<void()> worker_teardown_cb = nullptr);
void log(const details::log_msg& msg);
void log(const details::log_msg &msg);
// stop logging and join the back thread
~async_log_helper();
async_log_helper(const async_log_helper&) = delete;
async_log_helper& operator=(const async_log_helper&) = delete;
async_log_helper(const async_log_helper &) = delete;
async_log_helper &operator=(const async_log_helper &) = delete;
void set_formatter(formatter_ptr msg_formatter);
@ -173,49 +167,41 @@ private:
// worker thread
std::thread _worker_thread;
void push_msg(async_msg&& new_msg);
void push_msg(async_msg &&new_msg);
// worker thread main loop
void worker_loop();
// pop next message from the queue and process it. will set the last_pop to the pop time
// return false if termination of the queue is required
bool process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush);
bool process_next_msg(log_clock::time_point &last_pop, log_clock::time_point &last_flush);
void handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush);
void handle_flush_interval(log_clock::time_point &now, log_clock::time_point &last_flush);
// sleep,yield or return immediately using the time passed since last message as a hint
static void sleep_or_yield(const spdlog::log_clock::time_point& now, const log_clock::time_point& last_op_time);
static void sleep_or_yield(const spdlog::log_clock::time_point &now, const log_clock::time_point &last_op_time);
// wait until the queue is empty
void wait_empty_q();
};
}
}
}} // namespace spdlog::details
///////////////////////////////////////////////////////////////////////////////
// async_sink class implementation
///////////////////////////////////////////////////////////////////////////////
inline spdlog::details::async_log_helper::async_log_helper(
formatter_ptr formatter,
std::vector<sink_ptr> sinks,
size_t queue_size,
log_err_handler err_handler,
const async_overflow_policy overflow_policy,
std::function<void()> worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms,
std::function<void()> worker_teardown_cb):
_formatter(std::move(formatter)),
_sinks(std::move(sinks)),
_q(queue_size),
_err_handler(std::move(err_handler)),
_flush_requested(false),
_terminate_requested(false),
_overflow_policy(overflow_policy),
_worker_warmup_cb(std::move(worker_warmup_cb)),
_flush_interval_ms(flush_interval_ms),
_worker_teardown_cb(std::move(worker_teardown_cb))
inline spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatter, std::vector<sink_ptr> sinks, size_t queue_size,
log_err_handler err_handler, const async_overflow_policy overflow_policy, std::function<void()> worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, std::function<void()> worker_teardown_cb)
: _formatter(std::move(formatter))
, _sinks(std::move(sinks))
, _q(queue_size)
, _err_handler(std::move(err_handler))
, _flush_requested(false)
, _terminate_requested(false)
, _overflow_policy(overflow_policy)
, _worker_warmup_cb(std::move(worker_warmup_cb))
, _flush_interval_ms(flush_interval_ms)
, _worker_teardown_cb(std::move(worker_teardown_cb))
{
_worker_thread = std::thread(&async_log_helper::worker_loop, this);
}
@ -234,14 +220,13 @@ inline spdlog::details::async_log_helper::~async_log_helper()
}
}
//Try to push and block until succeeded (if the policy is not to discard when the queue is full)
inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
// Try to push and block until succeeded (if the policy is not to discard when the queue is full)
inline void spdlog::details::async_log_helper::log(const details::log_msg &msg)
{
push_msg(async_msg(msg));
}
inline void spdlog::details::async_log_helper::push_msg(details::async_log_helper::async_msg&& new_msg)
inline void spdlog::details::async_log_helper::push_msg(details::async_log_helper::async_msg &&new_msg)
{
if (!_q.enqueue(std::move(new_msg)) && _overflow_policy != async_overflow_policy::discard_log_msg)
{
@ -251,8 +236,7 @@ inline void spdlog::details::async_log_helper::push_msg(details::async_log_helpe
{
now = details::os::now();
sleep_or_yield(now, last_op_time);
}
while (!_q.enqueue(std::move(new_msg)));
} while (!_q.enqueue(std::move(new_msg)));
}
}
@ -261,12 +245,13 @@ inline void spdlog::details::async_log_helper::flush(bool wait_for_q)
{
push_msg(async_msg(async_msg_type::flush));
if (wait_for_q)
wait_empty_q(); //return when queue is empty
wait_empty_q(); // return when queue is empty
}
inline void spdlog::details::async_log_helper::worker_loop()
{
if (_worker_warmup_cb) _worker_warmup_cb();
if (_worker_warmup_cb)
_worker_warmup_cb();
auto last_pop = details::os::now();
auto last_flush = last_pop;
auto active = true;
@ -280,19 +265,18 @@ inline void spdlog::details::async_log_helper::worker_loop()
{
_err_handler(ex.what());
}
catch(...)
catch (...)
{
_err_handler("Unknown exeption in async logger worker loop.");
}
}
if (_worker_teardown_cb) _worker_teardown_cb();
if (_worker_teardown_cb)
_worker_teardown_cb();
}
// process next message in the queue
// return true if this thread should still be active (while no terminate msg was received)
inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush)
inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_point &last_pop, log_clock::time_point &last_flush)
{
async_msg incoming_async_msg;
@ -334,9 +318,10 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
}
// flush all sinks if _flush_interval_ms has expired
inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush)
inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::time_point &now, log_clock::time_point &last_flush)
{
auto should_flush = _flush_requested || (_flush_interval_ms != std::chrono::milliseconds::zero() && now - last_flush >= _flush_interval_ms);
auto should_flush =
_flush_requested || (_flush_interval_ms != std::chrono::milliseconds::zero() && now - last_flush >= _flush_interval_ms);
if (should_flush)
{
for (auto &s : _sinks)
@ -352,10 +337,11 @@ inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_f
}
// spin, yield or sleep. use the time passed since last message as a hint
inline void spdlog::details::async_log_helper::sleep_or_yield(const spdlog::log_clock::time_point& now, const spdlog::log_clock::time_point& last_op_time)
inline void spdlog::details::async_log_helper::sleep_or_yield(
const spdlog::log_clock::time_point &now, const spdlog::log_clock::time_point &last_op_time)
{
using std::chrono::milliseconds;
using std::chrono::microseconds;
using std::chrono::milliseconds;
auto time_since_op = now - last_op_time;

View File

@ -8,49 +8,39 @@
// Async Logger implementation
// Use an async_sink (queue per logger) to perform the logging in a worker thread
#include "../details/async_log_helper.h"
#include "../async_logger.h"
#include "../details/async_log_helper.h"
#include <string>
#include <functional>
#include <chrono>
#include <functional>
#include <memory>
#include <string>
template<class It>
inline spdlog::async_logger::async_logger(const std::string& logger_name,
const It& begin,
const It& end,
size_t queue_size,
const async_overflow_policy overflow_policy,
const std::function<void()>& worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms,
const std::function<void()>& worker_teardown_cb) :
logger(logger_name, begin, end),
_async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb))
template <class It>
inline spdlog::async_logger::async_logger(const std::string &logger_name, const It &begin, const It &end, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
: logger(logger_name, begin, end)
, _async_log_helper(new details::async_log_helper(
_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb))
{
}
inline spdlog::async_logger::async_logger(const std::string& logger_name,
sinks_init_list sinks_list,
size_t queue_size,
const async_overflow_policy overflow_policy,
const std::function<void()>& worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms,
const std::function<void()>& worker_teardown_cb) :
async_logger(logger_name, sinks_list.begin(), sinks_list.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
inline spdlog::async_logger::async_logger(const std::string& logger_name,
sink_ptr single_sink,
size_t queue_size,
const async_overflow_policy overflow_policy,
const std::function<void()>& worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms,
const std::function<void()>& worker_teardown_cb) :
async_logger(logger_name,
inline spdlog::async_logger::async_logger(const std::string &logger_name, sinks_init_list sinks_list, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
: async_logger(logger_name, sinks_list.begin(), sinks_list.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms,
worker_teardown_cb)
{
std::move(single_sink)
}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
}
inline spdlog::async_logger::async_logger(const std::string &logger_name, sink_ptr single_sink, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
: async_logger(
logger_name, {std::move(single_sink)}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb)
{
}
inline void spdlog::async_logger::flush()
{
@ -62,28 +52,25 @@ inline void spdlog::async_logger::set_error_handler(spdlog::log_err_handler err_
{
_err_handler = err_handler;
_async_log_helper->set_error_handler(err_handler);
}
inline spdlog::log_err_handler spdlog::async_logger::error_handler()
{
return _err_handler;
}
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)
{
_formatter = msg_formatter;
_async_log_helper->set_formatter(_formatter);
}
inline void spdlog::async_logger::_set_pattern(const std::string& pattern, pattern_time_type pattern_time)
inline void spdlog::async_logger::_set_pattern(const std::string &pattern, pattern_time_type pattern_time)
{
_formatter = std::make_shared<pattern_formatter>(pattern, pattern_time);
_async_log_helper->set_formatter(_formatter);
}
inline void spdlog::async_logger::_sink_it(details::log_msg& msg)
inline void spdlog::async_logger::_sink_it(details::log_msg &msg)
{
try
{
@ -98,10 +85,9 @@ inline void spdlog::async_logger::_sink_it(details::log_msg& msg)
{
_err_handler(ex.what());
}
catch(...)
catch (...)
{
_err_handler("Unknown exception in logger " + _name);
throw;
}
}

View File

@ -9,20 +9,17 @@
// When failing to open a file, retry several times(5) with small delay between the tries(10 ms)
// Throw spdlog_ex exception on errors
#include "../details/os.h"
#include "../details/log_msg.h"
#include "../details/os.h"
#include <cerrno>
#include <chrono>
#include <cstdio>
#include <string>
#include <thread>
#include <tuple>
#include <cerrno>
namespace spdlog
{
namespace details
{
namespace spdlog { namespace details {
class file_helper
{
@ -33,16 +30,15 @@ public:
explicit file_helper() = default;
file_helper(const file_helper&) = delete;
file_helper& operator=(const file_helper&) = delete;
file_helper(const file_helper &) = delete;
file_helper &operator=(const file_helper &) = delete;
~file_helper()
{
close();
}
void open(const filename_t& fname, bool truncate = false)
void open(const filename_t &fname, bool truncate = false)
{
close();
auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
@ -63,7 +59,6 @@ public:
if (_filename.empty())
throw spdlog_ex("Failed re opening file - was not opened before");
open(_filename, truncate);
}
void flush()
@ -80,7 +75,7 @@ public:
}
}
void write(const log_msg& msg)
void write(const log_msg &msg)
{
size_t msg_size = msg.formatted.size();
auto data = msg.formatted.data();
@ -97,12 +92,12 @@ public:
return os::filesize(_fd);
}
const filename_t& filename() const
const filename_t &filename() const
{
return _filename;
}
static bool file_exists(const filename_t& fname)
static bool file_exists(const filename_t &fname)
{
return os::file_exists(fname);
}
@ -120,7 +115,7 @@ public:
// ".mylog" => (".mylog". "")
// "my_folder/.mylog" => ("my_folder/.mylog", "")
// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
static std::tuple<filename_t, filename_t> split_by_extenstion(const spdlog::filename_t& fname)
static std::tuple<filename_t, filename_t> split_by_extenstion(const spdlog::filename_t &fname)
{
auto ext_index = fname.rfind('.');
@ -138,8 +133,7 @@ public:
}
private:
FILE* _fd{ nullptr };
FILE *_fd{nullptr};
filename_t _filename;
};
}
}
}} // namespace spdlog::details

View File

@ -11,16 +11,13 @@
#include <string>
#include <utility>
namespace spdlog
{
namespace details
{
namespace spdlog { namespace details {
struct log_msg
{
log_msg() = default;
log_msg(const std::string *loggers_name, level::level_enum lvl) :
logger_name(loggers_name),
level(lvl)
log_msg(const std::string *loggers_name, level::level_enum lvl)
: logger_name(loggers_name)
, level(lvl)
{
#ifndef SPDLOG_NO_DATETIME
time = os::now();
@ -31,18 +28,16 @@ struct log_msg
#endif
}
log_msg(const log_msg& other) = delete;
log_msg& operator=(log_msg&& other) = delete;
log_msg(log_msg&& other) = delete;
log_msg(const log_msg &other) = delete;
log_msg &operator=(log_msg &&other) = delete;
log_msg(log_msg &&other) = delete;
const std::string *logger_name{ nullptr };
const std::string *logger_name{nullptr};
level::level_enum level;
log_clock::time_point time;
size_t thread_id;
fmt::MemoryWriter raw;
fmt::MemoryWriter formatted;
size_t msg_id{ 0 };
size_t msg_id{0};
};
}
}
}} // namespace spdlog::details

View File

@ -13,54 +13,47 @@
// create logger with given name, sinks and the default pattern formatter
// all other ctors will call this one
template<class It>
inline spdlog::logger::logger(std::string logger_name, const It& begin, const It& end):
_name(std::move(logger_name)),
_sinks(begin, end),
_formatter(std::make_shared<pattern_formatter>("%+")),
_level(level::info),
_flush_level(level::off),
_last_err_time(0),
_msg_counter(1) // message counter will start from 1. 0-message id will be reserved for controll messages
template <class It>
inline spdlog::logger::logger(std::string logger_name, const It &begin, const It &end)
: _name(std::move(logger_name))
, _sinks(begin, end)
, _formatter(std::make_shared<pattern_formatter>("%+"))
, _level(level::info)
, _flush_level(level::off)
, _last_err_time(0)
, _msg_counter(1) // message counter will start from 1. 0-message id will be reserved for controll messages
{
_err_handler = [this](const std::string &msg)
{
this->_default_err_handler(msg);
};
_err_handler = [this](const std::string &msg) { this->_default_err_handler(msg); };
}
// ctor with sinks as init list
inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list):
logger(logger_name, sinks_list.begin(), sinks_list.end())
{}
inline spdlog::logger::logger(const std::string &logger_name, sinks_init_list sinks_list)
: logger(logger_name, sinks_list.begin(), sinks_list.end())
{
}
// ctor with single sink
inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink):
logger(logger_name,
inline spdlog::logger::logger(const std::string &logger_name, spdlog::sink_ptr single_sink)
: logger(logger_name, {std::move(single_sink)})
{
std::move(single_sink)
})
{}
}
inline spdlog::logger::~logger() = default;
inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter)
{
_set_formatter(std::move(msg_formatter));
}
inline void spdlog::logger::set_pattern(const std::string& pattern, pattern_time_type pattern_time)
inline void spdlog::logger::set_pattern(const std::string &pattern, pattern_time_type pattern_time)
{
_set_pattern(pattern, pattern_time);
}
template <typename... Args>
inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args)
template <typename... Args> inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Args &... args)
{
if (!should_log(lvl)) return;
if (!should_log(lvl))
return;
try
{
@ -77,17 +70,17 @@ inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Ar
{
_err_handler(ex.what());
}
catch(...)
catch (...)
{
_err_handler("Unknown exception in logger " + _name);
throw;
}
}
template <typename... Args>
inline void spdlog::logger::log(level::level_enum lvl, const char* msg)
template <typename... Args> inline void spdlog::logger::log(level::level_enum lvl, const char *msg)
{
if (!should_log(lvl)) return;
if (!should_log(lvl))
return;
try
{
details::log_msg log_msg(&_name, lvl);
@ -105,10 +98,10 @@ inline void spdlog::logger::log(level::level_enum lvl, const char* msg)
}
}
template<typename T>
inline void spdlog::logger::log(level::level_enum lvl, const T& msg)
template <typename T> inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
{
if (!should_log(lvl)) return;
if (!should_log(lvl))
return;
try
{
details::log_msg log_msg(&_name, lvl);
@ -126,98 +119,78 @@ inline void spdlog::logger::log(level::level_enum lvl, const T& msg)
}
}
template <typename Arg1, typename... Args>
inline void spdlog::logger::trace(const char* fmt, const Arg1 &arg1, const Args&... args)
template <typename Arg1, typename... Args> inline void spdlog::logger::trace(const char *fmt, const Arg1 &arg1, const Args &... args)
{
log(level::trace, fmt, arg1, args...);
}
template <typename Arg1, typename... Args>
inline void spdlog::logger::debug(const char* fmt, const Arg1 &arg1, const Args&... args)
template <typename Arg1, typename... Args> inline void spdlog::logger::debug(const char *fmt, const Arg1 &arg1, const Args &... args)
{
log(level::debug, fmt, arg1, args...);
}
template <typename Arg1, typename... Args>
inline void spdlog::logger::info(const char* fmt, const Arg1 &arg1, const Args&... args)
template <typename Arg1, typename... Args> inline void spdlog::logger::info(const char *fmt, const Arg1 &arg1, const Args &... args)
{
log(level::info, fmt, arg1, args...);
}
template <typename Arg1, typename... Args>
inline void spdlog::logger::warn(const char* fmt, const Arg1 &arg1, const Args&... args)
template <typename Arg1, typename... Args> inline void spdlog::logger::warn(const char *fmt, const Arg1 &arg1, const Args &... args)
{
log(level::warn, fmt, arg1, args...);
}
template <typename Arg1, typename... Args>
inline void spdlog::logger::error(const char* fmt, const Arg1 &arg1, const Args&... args)
template <typename Arg1, typename... Args> inline void spdlog::logger::error(const char *fmt, const Arg1 &arg1, const Args &... args)
{
log(level::err, fmt, arg1, args...);
}
template <typename Arg1, typename... Args>
inline void spdlog::logger::critical(const char* fmt, const Arg1 &arg1, const Args&... args)
template <typename Arg1, typename... Args> inline void spdlog::logger::critical(const char *fmt, const Arg1 &arg1, const Args &... args)
{
log(level::critical, fmt, arg1, args...);
}
template<typename T>
inline void spdlog::logger::trace(const T& msg)
template <typename T> inline void spdlog::logger::trace(const T &msg)
{
log(level::trace, msg);
}
template<typename T>
inline void spdlog::logger::debug(const T& msg)
template <typename T> inline void spdlog::logger::debug(const T &msg)
{
log(level::debug, msg);
}
template<typename T>
inline void spdlog::logger::info(const T& msg)
template <typename T> inline void spdlog::logger::info(const T &msg)
{
log(level::info, msg);
}
template<typename T>
inline void spdlog::logger::warn(const T& msg)
template <typename T> inline void spdlog::logger::warn(const T &msg)
{
log(level::warn, msg);
}
template<typename T>
inline void spdlog::logger::error(const T& msg)
template <typename T> inline void spdlog::logger::error(const T &msg)
{
log(level::err, msg);
}
template<typename T>
inline void spdlog::logger::critical(const T& msg)
template <typename T> inline void spdlog::logger::critical(const T &msg)
{
log(level::critical, msg);
}
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
#include <codecvt>
#include <locale>
template <typename... Args>
inline void spdlog::logger::log(level::level_enum lvl, const wchar_t* msg)
template <typename... Args> inline void spdlog::logger::log(level::level_enum lvl, const wchar_t *msg)
{
std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
log(lvl, conv.to_bytes(msg));
}
template <typename... Args>
inline void spdlog::logger::log(level::level_enum lvl, const wchar_t* fmt, const Args&... args)
template <typename... Args> inline void spdlog::logger::log(level::level_enum lvl, const wchar_t *fmt, const Args &... args)
{
fmt::WMemoryWriter wWriter;
@ -225,51 +198,42 @@ inline void spdlog::logger::log(level::level_enum lvl, const wchar_t* fmt, const
log(lvl, wWriter.c_str());
}
template <typename... Args>
inline void spdlog::logger::trace(const wchar_t* fmt, const Args&... args)
template <typename... Args> inline void spdlog::logger::trace(const wchar_t *fmt, const Args &... args)
{
log(level::trace, fmt, args...);
}
template <typename... Args>
inline void spdlog::logger::debug(const wchar_t* fmt, const Args&... args)
template <typename... Args> inline void spdlog::logger::debug(const wchar_t *fmt, const Args &... args)
{
log(level::debug, fmt, args...);
}
template <typename... Args>
inline void spdlog::logger::info(const wchar_t* fmt, const Args&... args)
template <typename... Args> inline void spdlog::logger::info(const wchar_t *fmt, const Args &... args)
{
log(level::info, fmt, args...);
}
template <typename... Args>
inline void spdlog::logger::warn(const wchar_t* fmt, const Args&... args)
template <typename... Args> inline void spdlog::logger::warn(const wchar_t *fmt, const Args &... args)
{
log(level::warn, fmt, args...);
}
template <typename... Args>
inline void spdlog::logger::error(const wchar_t* fmt, const Args&... args)
template <typename... Args> inline void spdlog::logger::error(const wchar_t *fmt, const Args &... args)
{
log(level::err, fmt, args...);
}
template <typename... Args>
inline void spdlog::logger::critical(const wchar_t* fmt, const Args&... args)
template <typename... Args> inline void spdlog::logger::critical(const wchar_t *fmt, const Args &... args)
{
log(level::critical, fmt, args...);
}
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
//
// name and level
//
inline const std::string& spdlog::logger::name() const
inline const std::string &spdlog::logger::name() const
{
return _name;
}
@ -307,7 +271,7 @@ inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) cons
//
// protected virtual called at end of each user log call (if enabled) by the line_logger
//
inline void spdlog::logger::_sink_it(details::log_msg& msg)
inline void spdlog::logger::_sink_it(details::log_msg &msg)
{
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
_incr_msg_counter(msg);
@ -315,17 +279,17 @@ inline void spdlog::logger::_sink_it(details::log_msg& msg)
_formatter->format(msg);
for (auto &sink : _sinks)
{
if( sink->should_log( msg.level))
if (sink->should_log(msg.level))
{
sink->log(msg);
}
}
if(_should_flush_on(msg))
if (_should_flush_on(msg))
flush();
}
inline void spdlog::logger::_set_pattern(const std::string& pattern, pattern_time_type pattern_time)
inline void spdlog::logger::_set_pattern(const std::string &pattern, pattern_time_type pattern_time)
{
_formatter = std::make_shared<pattern_formatter>(pattern, pattern_time);
}
@ -337,7 +301,7 @@ inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter)
inline void spdlog::logger::flush()
{
for (auto& sink : _sinks)
for (auto &sink : _sinks)
sink->flush();
}
@ -366,8 +330,7 @@ inline void spdlog::logger::_incr_msg_counter(details::log_msg &msg)
msg.msg_id = _msg_counter.fetch_add(1, std::memory_order_relaxed);
}
inline const std::vector<spdlog::sink_ptr>& spdlog::logger::sinks() const
inline const std::vector<spdlog::sink_ptr> &spdlog::logger::sinks() const
{
return _sinks;
}

View File

@ -48,23 +48,19 @@ Distributed under the MIT License (http://opensource.org/licenses/MIT)
#include <atomic>
#include <utility>
namespace spdlog
{
namespace details
{
namespace spdlog { namespace details {
template <typename T>
class mpmc_bounded_queue
template <typename T> class mpmc_bounded_queue
{
public:
using item_type = T;
explicit mpmc_bounded_queue(size_t buffer_size)
:max_size_(buffer_size),
buffer_(new cell_t[buffer_size]),
buffer_mask_(buffer_size - 1)
: max_size_(buffer_size)
, buffer_(new cell_t[buffer_size])
, 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)))
throw spdlog_ex("async logger queue size must be power of two");
@ -79,12 +75,12 @@ public:
delete[] buffer_;
}
mpmc_bounded_queue(mpmc_bounded_queue const&) = delete;
void operator=(mpmc_bounded_queue const&) = delete;
mpmc_bounded_queue(mpmc_bounded_queue const &) = delete;
void operator=(mpmc_bounded_queue const &) = delete;
bool enqueue(T&& data)
bool enqueue(T &&data)
{
cell_t* cell;
cell_t *cell;
size_t pos = enqueue_pos_.load(std::memory_order_relaxed);
for (;;)
{
@ -110,15 +106,14 @@ public:
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);
for (;;)
{
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 = static_cast<intptr_t>(seq) - static_cast<intptr_t>(pos + 1);
if (dif == 0)
{
@ -144,32 +139,30 @@ public:
front = enqueue_pos_.load(std::memory_order_acquire);
back = dequeue_pos_.load(std::memory_order_acquire);
front1 = enqueue_pos_.load(std::memory_order_relaxed);
}
while (front != front1);
} while (front != front1);
return back == front;
}
private:
struct cell_t
{
std::atomic<size_t> sequence_;
T data_;
std::atomic<size_t> sequence_;
T data_;
};
size_t const max_size_;
static size_t const cacheline_size = 64;
static size_t const cacheline_size = 64;
using cacheline_pad_t = char[cacheline_size];
cacheline_pad_t pad0_;
cell_t* const buffer_;
size_t const buffer_mask_;
cacheline_pad_t pad1_;
std::atomic<size_t> enqueue_pos_;
cacheline_pad_t pad2_;
std::atomic<size_t> dequeue_pos_;
cacheline_pad_t pad3_;
cacheline_pad_t pad0_;
cell_t *const buffer_;
size_t const buffer_mask_;
cacheline_pad_t pad1_;
std::atomic<size_t> enqueue_pos_;
cacheline_pad_t pad2_;
std::atomic<size_t> dequeue_pos_;
cacheline_pad_t pad3_;
};
} // ns details
} // ns spdlog
}} // namespace spdlog::details

View File

@ -8,10 +8,7 @@
#include <atomic>
// null, no cost dummy "mutex" and dummy "atomic" int
namespace spdlog
{
namespace details
{
namespace spdlog { namespace details {
struct null_mutex
{
void lock() {}
@ -27,8 +24,10 @@ struct null_atomic_int
int value;
null_atomic_int() = default;
explicit null_atomic_int(int val) : value(val)
{}
explicit null_atomic_int(int val)
: value(val)
{
}
int load(std::memory_order) const
{
@ -41,5 +40,4 @@ struct null_atomic_int
}
};
}
}
}} // namespace spdlog::details

View File

@ -6,30 +6,30 @@
#include "../common.h"
#include <algorithm>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <string>
#include <chrono>
#include <thread>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <sys/stat.h>
#include <sys/types.h>
#include <thread>
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX //prevent windows redefining min/max
#define NOMINMAX // prevent windows redefining min/max
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <io.h> // _get_osfhandle and _isatty support
#include <process.h> // _get_pid support
#include <io.h> // _get_osfhandle and _isatty support
#include <windows.h>
#ifdef __MINGW32__
#include <share.h>
@ -37,8 +37,8 @@
#else // unix
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef __linux__
#include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
@ -47,19 +47,13 @@
#include <sys/thr.h> //Use thr_self() syscall under FreeBSD to get thread id
#endif
#endif //unix
#endif // unix
#ifndef __has_feature // Clang - feature checking macros.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#ifndef __has_feature // Clang - feature checking macros.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif
namespace spdlog
{
namespace details
{
namespace os
{
namespace spdlog { namespace details { namespace os {
inline spdlog::log_clock::time_point now()
{
@ -68,14 +62,11 @@ inline spdlog::log_clock::time_point now()
timespec ts;
::clock_gettime(CLOCK_REALTIME_COARSE, &ts);
return std::chrono::time_point<log_clock, typename log_clock::duration>(
std::chrono::duration_cast<typename log_clock::duration>(
std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec)));
std::chrono::duration_cast<typename log_clock::duration>(std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec)));
#else
return log_clock::now();
#endif
}
inline std::tm localtime(const std::time_t &time_tt)
{
@ -114,24 +105,19 @@ inline std::tm gmtime()
std::time_t now_t = time(nullptr);
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 &&
tm1.tm_min == tm2.tm_min &&
tm1.tm_hour == tm2.tm_hour &&
tm1.tm_mday == tm2.tm_mday &&
tm1.tm_mon == tm2.tm_mon &&
tm1.tm_year == tm2.tm_year &&
tm1.tm_isdst == tm2.tm_isdst);
return (tm1.tm_sec == tm2.tm_sec && tm1.tm_min == tm2.tm_min && tm1.tm_hour == tm2.tm_hour && tm1.tm_mday == tm2.tm_mday &&
tm1.tm_mon == tm2.tm_mon && tm1.tm_year == tm2.tm_year && 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);
}
// eol definition
#if !defined (SPDLOG_EOL)
#if !defined(SPDLOG_EOL)
#ifdef _WIN32
#define SPDLOG_EOL "\r\n"
#else
@ -139,9 +125,7 @@ inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
#endif
#endif
SPDLOG_CONSTEXPR static const char* default_eol = SPDLOG_EOL;
SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL;
// folder separator
#ifdef _WIN32
@ -150,7 +134,6 @@ SPDLOG_CONSTEXPR static const char folder_sep = '\\';
SPDLOG_CONSTEXPR static const char folder_sep = '/';
#endif
inline void prevent_child_fd(FILE *f)
{
@ -167,9 +150,8 @@ inline void prevent_child_fd(FILE *f)
#endif
}
//fopen_s on non windows for writing
inline bool fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode)
// fopen_s on non windows for writing
inline bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode)
{
#ifdef _WIN32
#ifdef SPDLOG_WCHAR_FILENAMES
@ -177,7 +159,7 @@ inline bool fopen_s(FILE** fp, const filename_t& filename, const filename_t& mod
#else
*fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYWR);
#endif
#else //unix
#else // unix
*fp = fopen((filename.c_str()), mode.c_str());
#endif
@ -188,7 +170,6 @@ inline bool fopen_s(FILE** fp, const filename_t& filename, const filename_t& mod
return *fp == nullptr;
}
inline int remove(const filename_t &filename)
{
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
@ -198,7 +179,7 @@ inline int remove(const filename_t &filename)
#endif
}
inline int rename(const filename_t& filename1, const filename_t& filename2)
inline int rename(const filename_t &filename1, const filename_t &filename2)
{
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
return _wrename(filename1.c_str(), filename2.c_str());
@ -207,9 +188,8 @@ inline int rename(const filename_t& filename1, const filename_t& filename2)
#endif
}
//Return if file exists
inline bool file_exists(const filename_t& filename)
// Return if file exists
inline bool file_exists(const filename_t &filename)
{
#ifdef _WIN32
#ifdef SPDLOG_WCHAR_FILENAMES
@ -218,28 +198,25 @@ inline bool file_exists(const filename_t& filename)
auto attribs = GetFileAttributesA(filename.c_str());
#endif
return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY));
#else //common linux/unix all have the stat system call
#else // common linux/unix all have the stat system call
struct stat buffer;
return (stat(filename.c_str(), &buffer) == 0);
#endif
}
//Return file size according to open FILE* object
// Return file size according to open FILE* object
inline size_t filesize(FILE *f)
{
if (f == nullptr)
throw spdlog_ex("Failed getting file size. fd is null");
#if defined ( _WIN32) && !defined(__CYGWIN__)
#if defined(_WIN32) && !defined(__CYGWIN__)
int fd = _fileno(f);
#if _WIN64 //64 bits
#if _WIN64 // 64 bits
struct _stat64 st;
if (_fstat64(fd, &st) == 0)
return st.st_size;
#else //windows 32 bits
#else // windows 32 bits
long ret = _filelength(fd);
if (ret >= 0)
return static_cast<size_t>(ret);
@ -247,9 +224,9 @@ inline size_t filesize(FILE *f)
#else // unix
int fd = fileno(f);
//64 bits(but not in osx or cygwin, where fstat64 is deprecated)
// 64 bits(but not in osx or cygwin, where fstat64 is deprecated)
#if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) && !defined(__CYGWIN__)
struct stat64 st ;
struct stat64 st;
if (fstat64(fd, &st) == 0)
return static_cast<size_t>(st.st_size);
#else // unix 32 bits or cygwin
@ -261,11 +238,8 @@ inline size_t filesize(FILE *f)
throw spdlog_ex("Failed getting file size from fd", errno);
}
//Return utc offset in minutes or throw spdlog_ex on failure
inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
// Return utc offset in minutes or throw spdlog_ex on failure
inline int utc_minutes_offset(const std::tm &tm = details::os::localtime())
{
#ifdef _WIN32
@ -291,23 +265,22 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
// 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
struct helper
{
static long int calculate_gmt_offset(const std::tm & localtm = details::os::localtime(), const std::tm & gmtm = details::os::gmtime())
static long int calculate_gmt_offset(const std::tm &localtm = details::os::localtime(), const std::tm &gmtm = details::os::gmtime())
{
int local_year = localtm.tm_year + (1900 - 1);
int gmt_year = gmtm.tm_year + (1900 - 1);
long int days = (
// difference in day of year
localtm.tm_yday - gmtm.tm_yday
// difference in day of year
localtm.tm_yday -
gmtm.tm_yday
// + intervening leap days
+ ((local_year >> 2) - (gmt_year >> 2))
- (local_year / 100 - gmt_year / 100)
+ ((local_year / 100 >> 2) - (gmt_year / 100 >> 2))
// + intervening leap days
+ ((local_year >> 2) - (gmt_year >> 2)) - (local_year / 100 - gmt_year / 100) +
((local_year / 100 >> 2) - (gmt_year / 100 >> 2))
// + difference in years * 365 */
+ (long int)(local_year - gmt_year) * 365
);
// + difference in years * 365 */
+ (long int)(local_year - gmt_year) * 365);
long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour);
long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min);
@ -326,16 +299,16 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
#endif
}
//Return current thread id as size_t
//It exists because the std::this_thread::get_id() is much slower(especially under VS 2013)
// Return current thread id as size_t
// It exists because the std::this_thread::get_id() is much slower(especially under VS 2013)
inline size_t _thread_id()
{
#ifdef _WIN32
return static_cast<size_t>(::GetCurrentThreadId());
#elif __linux__
# if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
# define SYS_gettid __NR_gettid
# endif
#if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
#define SYS_gettid __NR_gettid
#endif
return static_cast<size_t>(syscall(SYS_gettid));
#elif __FreeBSD__
long tid;
@ -345,25 +318,23 @@ inline size_t _thread_id()
uint64_t tid;
pthread_threadid_np(nullptr, &tid);
return static_cast<size_t>(tid);
#else //Default to standard C++11 (other Unix)
#else // Default to standard C++11 (other Unix)
return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id()));
#endif
}
//Return current thread id as size_t (from thread local storage)
// Return current thread id as size_t (from thread local storage)
inline size_t thread_id()
{
#if defined(SPDLOG_DISABLE_TID_CACHING) || (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt ) || (defined(__clang__) && !__has_feature(cxx_thread_local))
#if defined(SPDLOG_DISABLE_TID_CACHING) || (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt) || \
(defined(__clang__) && !__has_feature(cxx_thread_local))
return _thread_id();
#else // cache thread id in tls
static thread_local const size_t tid = _thread_id();
return tid;
#endif
}
// This is avoid msvc issue in sleep_for that happens if the clock changes.
// See https://github.com/gabime/spdlog/issues/609
inline void sleep_for_millis(int milliseconds)
@ -377,21 +348,21 @@ inline void sleep_for_millis(int milliseconds)
// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
#define SPDLOG_FILENAME_T(s) L ## s
inline std::string filename_to_str(const filename_t& filename)
#define SPDLOG_FILENAME_T(s) L##s
inline std::string filename_to_str(const filename_t &filename)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> c;
return c.to_bytes(filename);
}
#else
#define SPDLOG_FILENAME_T(s) s
inline std::string filename_to_str(const filename_t& filename)
inline std::string filename_to_str(const filename_t &filename)
{
return filename;
}
#endif
inline std::string errno_to_string(char[256], char* res)
inline std::string errno_to_string(char[256], char *res)
{
return std::string(res);
}
@ -417,17 +388,17 @@ inline std::string errno_str(int err_num)
else
return "Unknown error";
#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || defined(__SUNPRO_CC) || \
((_POSIX_C_SOURCE >= 200112L) && ! defined(_GNU_SOURCE)) // posix version
#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || defined(__SUNPRO_CC) || \
((_POSIX_C_SOURCE >= 200112L) && !defined(_GNU_SOURCE)) // posix version
if (strerror_r(err_num, buf, buf_size) == 0)
return std::string(buf);
else
return "Unknown error";
#else // gnu version (might not use the given buf, so its retval pointer must be used)
#else // gnu version (might not use the given buf, so its retval pointer must be used)
auto err = strerror_r(err_num, buf, buf_size); // let compiler choose type
return errno_to_string(buf, err); // use overloading to select correct stringify function
return errno_to_string(buf, err); // use overloading to select correct stringify function
#endif
}
@ -439,10 +410,8 @@ inline int pid()
#else
return static_cast<int>(::getpid());
#endif
}
// Determine if the terminal supports colors
// Source: https://github.com/agauniyal/rang/
inline bool is_color_terminal()
@ -450,11 +419,8 @@ inline bool is_color_terminal()
#ifdef _WIN32
return true;
#else
static constexpr const char* Terms[] =
{
"ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm",
"linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm"
};
static constexpr const char *Terms[] = {
"ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", "linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm"};
const char *env_p = std::getenv("TERM");
if (env_p == nullptr)
@ -462,19 +428,15 @@ inline bool is_color_terminal()
return false;
}
static const bool result = std::any_of(
std::begin(Terms), std::end(Terms), [&](const char* term)
{
return std::strstr(env_p, term) != nullptr;
});
static const bool result =
std::any_of(std::begin(Terms), std::end(Terms), [&](const char *term) { return std::strstr(env_p, term) != nullptr; });
return result;
#endif
}
// Detrmine if the terminal attached
// Source: https://github.com/agauniyal/rang/
inline bool in_terminal(FILE* file)
inline bool in_terminal(FILE *file)
{
#ifdef _WIN32
@ -483,6 +445,4 @@ inline bool in_terminal(FILE* file)
return isatty(fileno(file)) != 0;
#endif
}
} //os
} //details
} //spdlog
}}} // namespace spdlog::details::os

View File

@ -5,11 +5,12 @@
#pragma once
#include "../formatter.h"
#include "../details/log_msg.h"
#include "../details/os.h"
#include "../fmt/fmt.h"
#include "../formatter.h"
#include <array>
#include <chrono>
#include <ctime>
#include <memory>
@ -18,17 +19,13 @@
#include <thread>
#include <utility>
#include <vector>
#include <array>
namespace spdlog
{
namespace details
{
namespace spdlog { namespace details {
class flag_formatter
{
public:
virtual ~flag_formatter() = default;
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;
};
///////////////////////////////////////////////////////////////////////
@ -36,7 +33,7 @@ public:
///////////////////////////////////////////////////////////////////////
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;
}
@ -45,7 +42,7 @@ class name_formatter : public flag_formatter
// log level appender
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);
}
@ -54,7 +51,7 @@ class level_formatter : public flag_formatter
// short log level appender
class short_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_short_str(msg.level);
}
@ -64,74 +61,75 @@ class short_level_formatter : public flag_formatter
// Date time pattern appenders
///////////////////////////////////////////////////////////////////////
static const char* ampm(const tm& t)
static const char *ampm(const tm &t)
{
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;
}
//Abbreviated weekday name
static const std::string days[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
// Abbreviated weekday name
static const std::string days[]{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
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];
}
};
//Full weekday name
static const std::string full_days[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
// Full weekday name
static const std::string full_days[]{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
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];
}
};
//Abbreviated month
static const std::string months[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" };
// Abbreviated month
static const std::string months[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"};
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];
}
};
//Full month name
static const std::string full_months[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
// Full month name
static const std::string full_months[]{
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
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];
}
};
//write 2 ints separated by sep with padding of 2
static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, char sep)
// write 2 ints separated by sep with padding of 2
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');
return w;
}
//write 3 ints separated by sep with padding of 2
static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v3, char sep)
// write 3 ints separated by sep with padding of 2
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');
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 SPDLOG_FINAL : 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 << ' ';
pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900;
@ -141,7 +139,7 @@ class c_formatter SPDLOG_FINAL : public flag_formatter
// year - 2 digit
class C_formatter SPDLOG_FINAL : 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');
}
@ -150,7 +148,7 @@ class C_formatter SPDLOG_FINAL : public flag_formatter
// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01
class D_formatter SPDLOG_FINAL : 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, '/');
}
@ -159,7 +157,7 @@ class D_formatter SPDLOG_FINAL : public flag_formatter
// year - 4 digit
class Y_formatter SPDLOG_FINAL : 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;
}
@ -168,7 +166,7 @@ class Y_formatter SPDLOG_FINAL : public flag_formatter
// month 1-12
class m_formatter SPDLOG_FINAL : 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');
}
@ -177,7 +175,7 @@ class m_formatter SPDLOG_FINAL : public flag_formatter
// day of month 1-31
class d_formatter SPDLOG_FINAL : 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');
}
@ -186,7 +184,7 @@ class d_formatter SPDLOG_FINAL : public flag_formatter
// hours in 24 format 0-23
class H_formatter SPDLOG_FINAL : 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');
}
@ -195,7 +193,7 @@ class H_formatter SPDLOG_FINAL : public flag_formatter
// hours in 12 format 1-12
class I_formatter SPDLOG_FINAL : 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');
}
@ -204,7 +202,7 @@ class I_formatter SPDLOG_FINAL : public flag_formatter
// minutes 0-59
class M_formatter SPDLOG_FINAL : 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');
}
@ -213,7 +211,7 @@ class M_formatter SPDLOG_FINAL : public flag_formatter
// seconds 0-59
class S_formatter SPDLOG_FINAL : 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');
}
@ -222,7 +220,7 @@ class S_formatter SPDLOG_FINAL : public flag_formatter
// milliseconds
class e_formatter SPDLOG_FINAL : 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 millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
@ -233,7 +231,7 @@ class e_formatter SPDLOG_FINAL : public flag_formatter
// microseconds
class f_formatter SPDLOG_FINAL : 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 micros = std::chrono::duration_cast<std::chrono::microseconds>(duration).count() % 1000000;
@ -244,7 +242,7 @@ class f_formatter SPDLOG_FINAL : public flag_formatter
// nanoseconds
class F_formatter SPDLOG_FINAL : 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 ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 1000000000;
@ -254,7 +252,7 @@ class F_formatter SPDLOG_FINAL : public flag_formatter
class E_formatter SPDLOG_FINAL : 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 seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
@ -265,7 +263,7 @@ class E_formatter SPDLOG_FINAL : public flag_formatter
// AM/PM
class p_formatter SPDLOG_FINAL : 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);
}
@ -274,7 +272,7 @@ class p_formatter SPDLOG_FINAL : public flag_formatter
// 12 hour clock 02:55:02 pm
class r_formatter SPDLOG_FINAL : 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);
}
@ -283,7 +281,7 @@ class r_formatter SPDLOG_FINAL : public flag_formatter
// 24-hour HH:MM time, equivalent to %H:%M
class R_formatter SPDLOG_FINAL : 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, ':');
}
@ -292,7 +290,7 @@ class R_formatter SPDLOG_FINAL : public flag_formatter
// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
class T_formatter SPDLOG_FINAL : 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, ':');
}
@ -305,10 +303,10 @@ public:
const std::chrono::seconds cache_refresh = std::chrono::seconds(5);
z_formatter() = default;
z_formatter(const z_formatter&) = delete;
z_formatter& operator=(const z_formatter&) = delete;
z_formatter(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
int total_minutes = get_cached_offset(msg, tm_time);
@ -334,12 +332,13 @@ public:
msg.formatted << sign;
pad_n_join(msg.formatted, h, m, ':');
}
private:
log_clock::time_point _last_update{ std::chrono::seconds(0) };
int _offset_minutes{ 0 };
log_clock::time_point _last_update{std::chrono::seconds(0)};
int _offset_minutes{0};
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)
{
std::lock_guard<std::mutex> l(_mutex);
if (msg.time - _last_update >= cache_refresh)
@ -354,7 +353,7 @@ private:
// Thread id
class t_formatter SPDLOG_FINAL : 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.thread_id;
}
@ -363,7 +362,7 @@ class t_formatter SPDLOG_FINAL : public flag_formatter
// Current pid
class pid_formatter SPDLOG_FINAL : 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 << details::os::pid();
}
@ -372,7 +371,7 @@ class pid_formatter SPDLOG_FINAL : public flag_formatter
// message counter formatter
class i_formatter SPDLOG_FINAL : 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::pad(msg.msg_id, 6, '0');
}
@ -380,7 +379,7 @@ class i_formatter SPDLOG_FINAL : public flag_formatter
class v_formatter SPDLOG_FINAL : 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());
}
@ -389,18 +388,20 @@ class v_formatter SPDLOG_FINAL : public flag_formatter
class ch_formatter SPDLOG_FINAL : public flag_formatter
{
public:
explicit ch_formatter(char ch): _ch(ch)
{}
void format(details::log_msg& msg, const std::tm&) override
explicit ch_formatter(char ch)
: _ch(ch)
{
}
void format(details::log_msg &msg, const std::tm &) override
{
msg.formatted << _ch;
}
private:
char _ch;
};
//aggregate user chars to display as is
// aggregate user chars to display as is
class aggregate_formatter SPDLOG_FINAL : public flag_formatter
{
public:
@ -410,10 +411,11 @@ public:
{
_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;
}
private:
std::string _str;
};
@ -422,7 +424,7 @@ private:
// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
class full_formatter SPDLOG_FINAL : 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
{
#ifndef SPDLOG_NO_DATETIME
auto duration = msg.time.time_since_epoch();
@ -441,7 +443,6 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
level::to_str(msg.level),
msg.raw.str());*/
// 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) << '-'
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_mon + 1), 2, '0') << '-'
@ -451,7 +452,7 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.'
<< fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] ";
//no datetime needed
// no datetime needed
#else
(void)tm_time;
#endif
@ -465,21 +466,18 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
}
};
}
}
}} // namespace spdlog::details
///////////////////////////////////////////////////////////////////////////////
// pattern_formatter inline impl
///////////////////////////////////////////////////////////////////////////////
inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern, pattern_time_type pattern_time, std::string eol) :
_eol(std::move(eol)),
_pattern_time(pattern_time)
inline spdlog::pattern_formatter::pattern_formatter(const std::string &pattern, pattern_time_type pattern_time, std::string eol)
: _eol(std::move(eol))
, _pattern_time(pattern_time)
{
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();
std::unique_ptr<details::aggregate_formatter> user_chars;
@ -487,7 +485,7 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string& patter
{
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));
if (++it != end)
handle_flag(*it);
@ -501,11 +499,10 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string& patter
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));
}
}
inline void spdlog::pattern_formatter::handle_flag(char flag)
{
@ -524,105 +521,105 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
_formatters.emplace_back(new details::short_level_formatter());
break;
case('t'):
case ('t'):
_formatters.emplace_back(new details::t_formatter());
break;
case('v'):
case ('v'):
_formatters.emplace_back(new details::v_formatter());
break;
case('a'):
case ('a'):
_formatters.emplace_back(new details::a_formatter());
break;
case('A'):
case ('A'):
_formatters.emplace_back(new details::A_formatter());
break;
case('b'):
case('h'):
case ('b'):
case ('h'):
_formatters.emplace_back(new details::b_formatter());
break;
case('B'):
case ('B'):
_formatters.emplace_back(new details::B_formatter());
break;
case('c'):
case ('c'):
_formatters.emplace_back(new details::c_formatter());
break;
case('C'):
case ('C'):
_formatters.emplace_back(new details::C_formatter());
break;
case('Y'):
case ('Y'):
_formatters.emplace_back(new details::Y_formatter());
break;
case('D'):
case('x'):
case ('D'):
case ('x'):
_formatters.emplace_back(new details::D_formatter());
break;
case('m'):
case ('m'):
_formatters.emplace_back(new details::m_formatter());
break;
case('d'):
case ('d'):
_formatters.emplace_back(new details::d_formatter());
break;
case('H'):
case ('H'):
_formatters.emplace_back(new details::H_formatter());
break;
case('I'):
case ('I'):
_formatters.emplace_back(new details::I_formatter());
break;
case('M'):
case ('M'):
_formatters.emplace_back(new details::M_formatter());
break;
case('S'):
case ('S'):
_formatters.emplace_back(new details::S_formatter());
break;
case('e'):
case ('e'):
_formatters.emplace_back(new details::e_formatter());
break;
case('f'):
case ('f'):
_formatters.emplace_back(new details::f_formatter());
break;
case('F'):
case ('F'):
_formatters.emplace_back(new details::F_formatter());
break;
case('E'):
case ('E'):
_formatters.emplace_back(new details::E_formatter());
break;
case('p'):
case ('p'):
_formatters.emplace_back(new details::p_formatter());
break;
case('r'):
case ('r'):
_formatters.emplace_back(new details::r_formatter());
break;
case('R'):
case ('R'):
_formatters.emplace_back(new details::R_formatter());
break;
case('T'):
case('X'):
case ('T'):
case ('X'):
_formatters.emplace_back(new details::T_formatter());
break;
case('z'):
case ('z'):
_formatters.emplace_back(new details::z_formatter());
break;
@ -634,19 +631,18 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
_formatters.emplace_back(new details::pid_formatter());
break;
case ('i'):
_formatters.emplace_back(new details::i_formatter());
break;
default: //Unknown flag appears as is
default: // Unknown flag appears as is
_formatters.emplace_back(new details::ch_formatter('%'));
_formatters.emplace_back(new details::ch_formatter(flag));
break;
}
}
inline std::tm spdlog::pattern_formatter::get_time(details::log_msg& msg)
inline std::tm spdlog::pattern_formatter::get_time(details::log_msg &msg)
{
if (_pattern_time == pattern_time_type::local)
{
@ -655,7 +651,7 @@ inline std::tm spdlog::pattern_formatter::get_time(details::log_msg& msg)
return details::os::gmtime(log_clock::to_time_t(msg.time));
}
inline void spdlog::pattern_formatter::format(details::log_msg& msg)
inline void spdlog::pattern_formatter::format(details::log_msg &msg)
{
#ifndef SPDLOG_NO_DATETIME
@ -667,6 +663,6 @@ inline void spdlog::pattern_formatter::format(details::log_msg& msg)
{
f->format(msg, tm_time);
}
//write eol
// write eol
msg.formatted.write(_eol.data(), _eol.size());
}

View File

@ -10,10 +10,10 @@
// If user requests a non existing logger, nullptr will be returned
// This class is thread safe
#include "../details/null_mutex.h"
#include "../logger.h"
#include "../async_logger.h"
#include "../common.h"
#include "../details/null_mutex.h"
#include "../logger.h"
#include <chrono>
#include <functional>
@ -22,16 +22,12 @@
#include <string>
#include <unordered_map>
namespace spdlog
{
namespace details
{
template <class Mutex>
class registry_t
namespace spdlog { namespace details {
template <class Mutex> class registry_t
{
public:
registry_t<Mutex>(const registry_t<Mutex>&) = delete;
registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete;
registry_t<Mutex>(const registry_t<Mutex> &) = delete;
registry_t<Mutex> &operator=(const registry_t<Mutex> &) = delete;
void register_logger(std::shared_ptr<logger> logger)
{
@ -41,21 +37,21 @@ public:
_loggers[logger_name] = logger;
}
std::shared_ptr<logger> get(const std::string& logger_name)
std::shared_ptr<logger> get(const std::string &logger_name)
{
std::lock_guard<Mutex> lock(_mutex);
auto found = _loggers.find(logger_name);
return found == _loggers.end() ? nullptr : found->second;
}
template<class It>
std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
template <class It> std::shared_ptr<logger> create(const std::string &logger_name, const It &sinks_begin, const It &sinks_end)
{
std::lock_guard<Mutex> lock(_mutex);
throw_if_exists(logger_name);
std::shared_ptr<logger> new_logger;
if (_async_mode)
new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb);
new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy,
_worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb);
else
new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
@ -68,18 +64,21 @@ public:
new_logger->set_level(_level);
new_logger->flush_on(_flush_level);
//Add to registry
// Add to registry
_loggers[logger_name] = new_logger;
return new_logger;
}
template<class It>
std::shared_ptr<async_logger> create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb, const It& sinks_begin, const It& sinks_end)
template <class It>
std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb, const It &sinks_begin,
const It &sinks_end)
{
std::lock_guard<Mutex> lock(_mutex);
throw_if_exists(logger_name);
auto new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
auto new_logger = std::make_shared<async_logger>(
logger_name, sinks_begin, sinks_end, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
if (_formatter)
new_logger->set_formatter(_formatter);
@ -90,7 +89,7 @@ public:
new_logger->set_level(_level);
new_logger->flush_on(_flush_level);
//Add to registry
// Add to registry
_loggers[logger_name] = new_logger;
return new_logger;
}
@ -102,7 +101,7 @@ public:
fun(l.second);
}
void drop(const std::string& logger_name)
void drop(const std::string &logger_name)
{
std::lock_guard<Mutex> lock(_mutex);
_loggers.erase(logger_name);
@ -114,46 +113,51 @@ public:
_loggers.clear();
}
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());
}
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});
}
std::shared_ptr<async_logger> create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb, sinks_init_list sinks)
std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb, sinks_init_list sinks)
{
return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks.begin(), sinks.end());
return create_async(
logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks.begin(), sinks.end());
}
std::shared_ptr<async_logger> create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb, sink_ptr sink)
std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb, sink_ptr sink)
{
return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, { sink });
return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, {sink});
}
void formatter(formatter_ptr f)
{
std::lock_guard<Mutex> lock(_mutex);
_formatter = f;
for (auto& l : _loggers)
for (auto &l : _loggers)
l.second->set_formatter(_formatter);
}
void set_pattern(const std::string& pattern)
void set_pattern(const std::string &pattern)
{
std::lock_guard<Mutex> lock(_mutex);
_formatter = std::make_shared<pattern_formatter>(pattern);
for (auto& l : _loggers)
for (auto &l : _loggers)
l.second->set_formatter(_formatter);
}
void set_level(level::level_enum log_level)
{
std::lock_guard<Mutex> lock(_mutex);
for (auto& l : _loggers)
for (auto &l : _loggers)
l.second->set_level(log_level);
_level = log_level;
}
@ -161,19 +165,20 @@ public:
void flush_on(level::level_enum log_level)
{
std::lock_guard<Mutex> lock(_mutex);
for (auto& l : _loggers)
for (auto &l : _loggers)
l.second->flush_on(log_level);
_flush_level = log_level;
}
void set_error_handler(log_err_handler handler)
{
for (auto& l : _loggers)
for (auto &l : _loggers)
l.second->set_error_handler(handler);
_err_handler = handler;
}
void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
{
std::lock_guard<Mutex> lock(_mutex);
_async_mode = true;
@ -190,7 +195,7 @@ public:
_async_mode = false;
}
static registry_t<Mutex>& instance()
static registry_t<Mutex> &instance()
{
static registry_t<Mutex> s_instance;
return s_instance;
@ -206,7 +211,7 @@ private:
}
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;
level::level_enum _level = level::info;
level::level_enum _flush_level = level::off;
@ -225,5 +230,4 @@ using registry = registry_t<spdlog::details::null_mutex>;
using registry = registry_t<std::mutex>;
#endif
}
}
}} // namespace spdlog::details

View File

@ -8,10 +8,10 @@
//
// Global registry functions
//
#include "../spdlog.h"
#include "../details/registry.h"
#include "../sinks/file_sinks.h"
#include "../sinks/stdout_sinks.h"
#include "../spdlog.h"
#ifdef SPDLOG_ENABLE_SYSLOG
#include "../sinks/syslog_sink.h"
#endif
@ -22,7 +22,6 @@
#include "../sinks/ansicolor_sink.h"
#endif
#ifdef __ANDROID__
#include "../sinks/android_sink.h"
#endif
@ -37,7 +36,7 @@ inline void spdlog::register_logger(std::shared_ptr<logger> logger)
return details::registry::instance().register_logger(std::move(logger));
}
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);
}
@ -48,58 +47,61 @@ inline void spdlog::drop(const std::string &name)
}
// Create multi/single threaded simple file logger
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate)
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate)
{
return create<spdlog::sinks::simple_file_sink_mt>(logger_name, filename, truncate);
}
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate)
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate)
{
return create<spdlog::sinks::simple_file_sink_st>(logger_name, filename, truncate);
}
// Create multi/single threaded rotating file logger
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files)
{
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files);
}
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files)
{
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files);
}
// 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 filename_t& filename, int hour, int minute)
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(
const std::string &logger_name, const filename_t &filename, int hour, int minute)
{
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, hour, minute);
}
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute)
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(
const std::string &logger_name, const filename_t &filename, int hour, int minute)
{
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, hour, minute);
}
//
// 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 spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance());
}
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 spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance());
}
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 spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance());
}
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 spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance());
}
@ -109,52 +111,51 @@ inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::strin
//
#if defined _WIN32 && !defined(__cplusplus_winrt)
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string& logger_name)
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string& logger_name)
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_st>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string& logger_name)
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_mt>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string& logger_name)
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_st>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
#else //ansi terminal colors
#else // ansi terminal colors
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string& logger_name)
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string& logger_name)
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_st>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string& logger_name)
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_stderr_sink_mt>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string& logger_name)
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_stderr_sink_st>();
return spdlog::details::registry::instance().create(logger_name, sink);
@ -163,60 +164,70 @@ inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string
#ifdef SPDLOG_ENABLE_SYSLOG
// 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, int syslog_facility)
inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(
const std::string &logger_name, const std::string &syslog_ident, int syslog_option, int syslog_facility)
{
return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option, syslog_facility);
}
#endif
#ifdef __ANDROID__
inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string& logger_name, const std::string& tag)
inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string &logger_name, const std::string &tag)
{
return create<spdlog::sinks::android_sink>(logger_name, tag);
}
#endif
// Create and register a logger a single sink
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const spdlog::sink_ptr& sink)
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string &logger_name, const spdlog::sink_ptr &sink)
{
return details::registry::instance().create(logger_name, sink);
}
//Create logger with multiple sinks
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks)
// Create logger with multiple 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);
}
template <typename Sink, typename... Args>
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, Args... args)
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string &logger_name, Args... 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>
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
template <class It>
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);
}
// Create and register an async logger with a single sink
inline std::shared_ptr<spdlog::logger> spdlog::create_async(const std::string& logger_name, const sink_ptr& sink, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
inline std::shared_ptr<spdlog::logger> spdlog::create_async(const std::string &logger_name, const sink_ptr &sink, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
{
return details::registry::instance().create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sink);
return details::registry::instance().create_async(
logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sink);
}
// Create and register an async logger with multiple sinks
inline std::shared_ptr<spdlog::logger> spdlog::create_async(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb )
inline std::shared_ptr<spdlog::logger> spdlog::create_async(const std::string &logger_name, sinks_init_list sinks, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
{
return details::registry::instance().create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks);
return details::registry::instance().create_async(
logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks);
}
template<class It>
inline std::shared_ptr<spdlog::logger> spdlog::create_async(const std::string& logger_name, const It& sinks_begin, const It& sinks_end, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
template <class It>
inline std::shared_ptr<spdlog::logger> spdlog::create_async(const std::string &logger_name, const It &sinks_begin, const It &sinks_end,
size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
{
return details::registry::instance().create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks_begin, sinks_end);
return details::registry::instance().create_async(
logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks_begin, sinks_end);
}
inline void spdlog::set_formatter(spdlog::formatter_ptr f)
@ -224,7 +235,7 @@ inline void spdlog::set_formatter(spdlog::formatter_ptr f)
details::registry::instance().formatter(std::move(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);
}
@ -244,7 +255,9 @@ inline void spdlog::set_error_handler(log_err_handler handler)
return details::registry::instance().set_error_handler(std::move(handler));
}
inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy,
const std::function<void()> &worker_warmup_cb, const std::chrono::milliseconds &flush_interval_ms,
const std::function<void()> &worker_teardown_cb)
{
details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
}

File diff suppressed because it is too large Load Diff

View File

@ -13,14 +13,11 @@
#include "format.h"
#include <ostream>
namespace fmt
{
namespace fmt {
namespace internal
{
namespace internal {
template <class Char>
class FormatBuf : public std::basic_streambuf<Char>
template <class Char> class FormatBuf : public std::basic_streambuf<Char>
{
private:
typedef typename std::basic_streambuf<Char>::int_type int_type;
@ -29,7 +26,10 @@ private:
Buffer<Char> &buffer_;
public:
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer) {}
FormatBuf(Buffer<Char> &buffer)
: buffer_(buffer)
{
}
protected:
// The put-area is actually always empty. This makes the implementation
@ -57,17 +57,15 @@ Yes &convert(std::ostream &);
struct DummyStream : std::ostream
{
DummyStream(); // Suppress a bogus warning in MSVC.
DummyStream(); // Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream.
template <typename T>
typename EnableIf<sizeof(T) == 0>::type operator<<(const T &);
template <typename T> typename EnableIf<sizeof(T) == 0>::type operator<<(const T &);
};
No &operator<<(std::ostream &, int);
template <typename T>
struct ConvertToIntImpl<T, true>
template <typename T> struct ConvertToIntImpl<T, true>
{
// Convert to int only if T doesn't have an overloaded operator<<.
enum
@ -78,12 +76,11 @@ struct ConvertToIntImpl<T, true>
// Write the content of w to os.
FMT_API void write(std::ostream &os, Writer &w);
} // namespace internal
} // namespace internal
// Formats a value.
template <typename Char, typename ArgFormatter_, typename T>
void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
const Char *&format_str, const T &value)
void format_arg(BasicFormatter<Char, ArgFormatter_> &f, const Char *&format_str, const T &value)
{
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
@ -93,7 +90,7 @@ void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
output << value;
BasicStringRef<Char> str(&buffer[0], buffer.size());
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
typedef internal::MakeArg<BasicFormatter<Char>> MakeArg;
format_str = f.format(format_str, MakeArg(str));
}
@ -108,10 +105,10 @@ void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
*/
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
} // namespace fmt
} // namespace fmt
#ifdef FMT_HEADER_ONLY
# include "ostream.cc"
#include "ostream.cc"
#endif
#endif // FMT_OSTREAM_H_
#endif // FMT_OSTREAM_H_

View File

@ -12,60 +12,60 @@
#if defined(__MINGW32__) || defined(__CYGWIN__)
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
# undef __STRICT_ANSI__
#undef __STRICT_ANSI__
#endif
#include <errno.h>
#include <fcntl.h> // for O_RDONLY
#include <locale.h> // for locale_t
#include <fcntl.h> // for O_RDONLY
#include <locale.h> // for locale_t
#include <stdio.h>
#include <stdlib.h> // for strtod_l
#include <stdlib.h> // for strtod_l
#include <cstddef>
#if defined __APPLE__ || defined(__FreeBSD__)
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif
#include "format.h"
#ifndef FMT_POSIX
# if defined(_WIN32) && !defined(__MINGW32__)
#if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols.
# define FMT_POSIX(call) _##call
# else
# define FMT_POSIX(call) call
# endif
#define FMT_POSIX(call) _##call
#else
#define FMT_POSIX(call) call
#endif
#endif
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
#ifdef FMT_SYSTEM
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else
# define FMT_SYSTEM(call) call
# ifdef _WIN32
#define FMT_SYSTEM(call) call
#ifdef _WIN32
// Fix warnings about deprecated symbols.
# define FMT_POSIX_CALL(call) ::_##call
# else
# define FMT_POSIX_CALL(call) ::call
# endif
#define FMT_POSIX_CALL(call) ::_##call
#else
#define FMT_POSIX_CALL(call) ::call
#endif
#endif
// Retries the expression while it evaluates to error_result and errno
// equals to EINTR.
#ifndef _WIN32
# define FMT_RETRY_VAL(result, expression, error_result) \
do { \
result = (expression); \
} while (result == error_result && errno == EINTR)
#define FMT_RETRY_VAL(result, expression, error_result) \
do \
{ \
result = (expression); \
} while (result == error_result && errno == EINTR)
#else
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
namespace fmt
{
namespace fmt {
// An error code.
class ErrorCode
@ -74,8 +74,7 @@ private:
int value_;
public:
explicit ErrorCode(int value = 0) FMT_NOEXCEPT :
value_(value) {}
explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
int get() const FMT_NOEXCEPT
{
@ -91,12 +90,14 @@ private:
friend class File;
explicit BufferedFile(FILE *f) : file_(f) {}
explicit BufferedFile(FILE *f)
: file_(f)
{
}
public:
// Constructs a BufferedFile object which doesn't represent any file.
BufferedFile() FMT_NOEXCEPT :
file_(FMT_NULL) {}
BufferedFile() FMT_NOEXCEPT : file_(FMT_NULL) {}
// Destroys the object closing the file it represents if any.
FMT_API ~BufferedFile() FMT_NOEXCEPT;
@ -115,12 +116,10 @@ private:
public:
// A "move constructor" for moving from a temporary.
BufferedFile(Proxy p) FMT_NOEXCEPT :
file_(p.file) {}
BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
// A "move constructor" for moving from an lvalue.
BufferedFile(BufferedFile &f) FMT_NOEXCEPT :
file_(f.file_)
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_)
{
f.file_ = FMT_NULL;
}
@ -156,13 +155,12 @@ private:
FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
public:
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT :
file_(other.file_)
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_)
{
other.file_ = FMT_NULL;
}
BufferedFile& operator=(BufferedFile &&other)
BufferedFile &operator=(BufferedFile &&other)
{
close();
file_ = other.file_;
@ -185,7 +183,7 @@ BufferedFile(BufferedFile &&other) FMT_NOEXCEPT :
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
FMT_API int (fileno)() const;
FMT_API int(fileno)() const;
void print(CStringRef format_str, const ArgList &args)
{
@ -203,10 +201,13 @@ BufferedFile(BufferedFile &&other) FMT_NOEXCEPT :
class File
{
private:
int fd_; // File descriptor.
int fd_; // File descriptor.
// Constructs a File object with a given descriptor.
explicit File(int fd) : fd_(fd) {}
explicit File(int fd)
: fd_(fd)
{
}
public:
// Possible values for the oflag argument to the constructor.
@ -214,12 +215,11 @@ public:
{
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
};
// Constructs a File object which doesn't represent any file.
File() FMT_NOEXCEPT :
fd_(-1) {}
File() FMT_NOEXCEPT : fd_(-1) {}
// Opens a file and constructs a File object representing this file.
FMT_API File(CStringRef path, int oflag);
@ -238,12 +238,10 @@ private:
public:
// A "move constructor" for moving from a temporary.
File(Proxy p) FMT_NOEXCEPT :
fd_(p.fd) {}
File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
// A "move constructor" for moving from an lvalue.
File(File &other) FMT_NOEXCEPT :
fd_(other.fd_)
File(File &other) FMT_NOEXCEPT : fd_(other.fd_)
{
other.fd_ = -1;
}
@ -279,13 +277,12 @@ private:
FMT_DISALLOW_COPY_AND_ASSIGN(File);
public:
File(File &&other) FMT_NOEXCEPT :
fd_(other.fd_)
File(File &&other) FMT_NOEXCEPT : fd_(other.fd_)
{
other.fd_ = -1;
}
File& operator=(File &&other)
File &operator=(File &&other)
{
close();
fd_ = other.fd_;
@ -340,9 +337,8 @@ File(File &&other) FMT_NOEXCEPT :
// Returns the memory page size.
long getpagesize();
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \
!defined(__ANDROID__) && !defined(__CYGWIN__)
# define FMT_LOCALE
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && !defined(__ANDROID__) && !defined(__CYGWIN__)
#define FMT_LOCALE
#endif
#ifdef FMT_LOCALE
@ -350,10 +346,13 @@ long getpagesize();
class Locale
{
private:
# ifdef _MSC_VER
#ifdef _MSC_VER
typedef _locale_t locale_t;
enum { LC_NUMERIC_MASK = LC_NUMERIC };
enum
{
LC_NUMERIC_MASK = LC_NUMERIC
};
static locale_t newlocale(int category_mask, const char *locale, locale_t)
{
@ -369,7 +368,7 @@ private:
{
return _strtod_l(nptr, endptr, locale);
}
# endif
#endif
locale_t locale_;
@ -378,7 +377,8 @@ private:
public:
typedef locale_t Type;
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL))
Locale()
: locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL))
{
if (!locale_)
FMT_THROW(fmt::SystemError(errno, "cannot create locale"));
@ -403,12 +403,11 @@ public:
return result;
}
};
#endif // FMT_LOCALE
} // namespace fmt
#endif // FMT_LOCALE
} // namespace fmt
#if !FMT_USE_RVALUE_REFERENCES
namespace std
{
namespace std {
// For compatibility with C++98.
inline fmt::BufferedFile &move(fmt::BufferedFile &f)
{
@ -418,7 +417,7 @@ inline fmt::File &move(fmt::File &f)
{
return f;
}
}
} // namespace std
#endif
#endif // FMT_POSIX_H_
#endif // FMT_POSIX_H_

View File

@ -10,23 +10,19 @@
#ifndef FMT_PRINTF_H_
#define FMT_PRINTF_H_
#include <algorithm> // std::fill_n
#include <limits> // std::numeric_limits
#include <algorithm> // std::fill_n
#include <limits> // std::numeric_limits
#include "ostream.h"
namespace fmt
{
namespace internal
{
namespace fmt {
namespace internal {
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template <bool IsSigned>
struct IntChecker
template <bool IsSigned> struct IntChecker
{
template <typename T>
static bool fits_in_int(T value)
template <typename T> static bool fits_in_int(T value)
{
unsigned max = std::numeric_limits<int>::max();
return value <= max;
@ -37,14 +33,11 @@ struct IntChecker
}
};
template <>
struct IntChecker<true>
template <> struct IntChecker<true>
{
template <typename T>
static bool fits_in_int(T value)
template <typename T> static bool fits_in_int(T value)
{
return value >= std::numeric_limits<int>::min() &&
value <= std::numeric_limits<int>::max();
return value >= std::numeric_limits<int>::min() && value <= std::numeric_limits<int>::max();
}
static bool fits_in_int(int)
{
@ -60,8 +53,7 @@ public:
FMT_THROW(FormatError("precision is not integer"));
}
template <typename T>
int visit_any_int(T value)
template <typename T> int visit_any_int(T value)
{
if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
FMT_THROW(FormatError("number is too big"));
@ -73,8 +65,7 @@ public:
class IsZeroInt : public ArgVisitor<IsZeroInt, bool>
{
public:
template <typename T>
bool visit_any_int(T value)
template <typename T> bool visit_any_int(T value)
{
return value == 0;
}
@ -99,14 +90,12 @@ public:
return 'p';
}
template <typename T>
char visit_any_int(T)
template <typename T> char visit_any_int(T)
{
return 'd';
}
template <typename T>
char visit_any_double(T)
template <typename T> char visit_any_double(T)
{
return 'g';
}
@ -117,24 +106,27 @@ public:
}
};
template <typename T, typename U>
struct is_same
template <typename T, typename U> struct is_same
{
enum { value = 0 };
enum
{
value = 0
};
};
template <typename T>
struct is_same<T, T>
template <typename T> struct is_same<T, T>
{
enum { value = 1 };
enum
{
value = 1
};
};
// An argument visitor that converts an integer argument to T for printf,
// if T is an integral type. If T is void, the argument is converted to
// corresponding signed or unsigned type depending on the type specifier:
// 'd' and 'i' - signed, other - unsigned)
template <typename T = void>
class ArgConverter : public ArgVisitor<ArgConverter<T>, void>
template <typename T = void> class ArgConverter : public ArgVisitor<ArgConverter<T>, void>
{
private:
internal::Arg &arg_;
@ -144,7 +136,10 @@ private:
public:
ArgConverter(internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type) {}
: arg_(arg)
, type_(type)
{
}
void visit_bool(bool value)
{
@ -158,8 +153,7 @@ public:
visit_any_int(value);
}
template <typename U>
void visit_any_int(U value)
template <typename U> void visit_any_int(U value)
{
bool is_signed = type_ == 'd' || type_ == 'i';
if (type_ == 's')
@ -168,8 +162,7 @@ public:
}
using internal::Arg;
typedef typename internal::Conditional<
is_same<T, void>::value, U, T>::type TargetType;
typedef typename internal::Conditional<is_same<T, void>::value, U, T>::type TargetType;
if (const_check(sizeof(TargetType) <= sizeof(int)))
{
// Extra casts are used to silence warnings.
@ -198,8 +191,7 @@ public:
else
{
arg_.type = Arg::ULONG_LONG;
arg_.ulong_long_value =
static_cast<typename internal::MakeUnsigned<U>::Type>(value);
arg_.ulong_long_value = static_cast<typename internal::MakeUnsigned<U>::Type>(value);
}
}
}
@ -214,10 +206,12 @@ private:
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
public:
explicit CharConverter(internal::Arg &arg) : arg_(arg) {}
explicit CharConverter(internal::Arg &arg)
: arg_(arg)
{
}
template <typename T>
void visit_any_int(T value)
template <typename T> void visit_any_int(T value)
{
arg_.type = internal::Arg::CHAR;
arg_.int_value = static_cast<char>(value);
@ -234,15 +228,17 @@ private:
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
public:
explicit WidthHandler(FormatSpec &spec) : spec_(spec) {}
explicit WidthHandler(FormatSpec &spec)
: spec_(spec)
{
}
void report_unhandled_arg()
{
FMT_THROW(FormatError("width is not integer"));
}
template <typename T>
unsigned visit_any_int(T value)
template <typename T> unsigned visit_any_int(T value)
{
typedef typename internal::IntTraits<T>::MainType UnsignedType;
UnsignedType width = static_cast<UnsignedType>(value);
@ -257,7 +253,7 @@ public:
return static_cast<unsigned>(width);
}
};
} // namespace internal
} // namespace internal
/**
\rst
@ -276,9 +272,7 @@ public:
superclass will be called.
\endrst
*/
template <typename Impl, typename Char, typename Spec>
class BasicPrintfArgFormatter :
public internal::ArgFormatterBase<Impl, Char, Spec>
template <typename Impl, typename Char, typename Spec> class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char, Spec>
{
private:
void write_null_pointer()
@ -298,7 +292,9 @@ public:
\endrst
*/
BasicPrintfArgFormatter(BasicWriter<Char> &w, Spec &s)
: internal::ArgFormatterBase<Impl, Char, Spec>(w, s) {}
: internal::ArgFormatterBase<Impl, Char, Spec>(w, s)
{
}
/** Formats an argument of type ``bool``. */
void visit_bool(bool value)
@ -371,19 +367,18 @@ public:
};
/** The default printf argument formatter. */
template <typename Char>
class PrintfArgFormatter :
public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>
template <typename Char> class PrintfArgFormatter : public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>
{
public:
/** Constructs an argument formatter object. */
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>(w, s) {}
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>(w, s)
{
}
};
/** This template formats data and writes the output to a writer. */
template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> >
class PrintfFormatter : private internal::FormatterBase
template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char>> class PrintfFormatter : private internal::FormatterBase
{
private:
BasicWriter<Char> &writer_;
@ -392,9 +387,7 @@ private:
// Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument.
internal::Arg get_arg(
const Char *s,
unsigned arg_index = (std::numeric_limits<unsigned>::max)());
internal::Arg get_arg(const Char *s, unsigned arg_index = (std::numeric_limits<unsigned>::max)());
// Parses argument index, flags and width and returns the argument index.
unsigned parse_header(const Char *&s, FormatSpec &spec);
@ -408,14 +401,16 @@ public:
\endrst
*/
explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w)
: FormatterBase(al), writer_(w) {}
: FormatterBase(al)
, writer_(w)
{
}
/** Formats stored arguments and writes the output to the writer. */
void format(BasicCStringRef<Char> format_str);
};
template <typename Char, typename AF>
void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
template <typename Char, typename AF> void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
{
for (;;)
{
@ -443,22 +438,17 @@ void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
}
}
template <typename Char, typename AF>
internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
unsigned arg_index)
template <typename Char, typename AF> internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s, unsigned arg_index)
{
(void)s;
const char *error = FMT_NULL;
internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ? next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
if (error)
FMT_THROW(FormatError(!*s ? "invalid format string" : error));
return arg;
}
template <typename Char, typename AF>
unsigned PrintfFormatter<Char, AF>::parse_header(
const Char *&s, FormatSpec &spec)
template <typename Char, typename AF> unsigned PrintfFormatter<Char, AF>::parse_header(const Char *&s, FormatSpec &spec)
{
unsigned arg_index = std::numeric_limits<unsigned>::max();
Char c = *s;
@ -467,7 +457,7 @@ unsigned PrintfFormatter<Char, AF>::parse_header(
// Parse an argument index (if followed by '$') or a width possibly
// preceded with '0' flag(s).
unsigned value = internal::parse_nonnegative_int(s);
if (*s == '$') // value is an argument index
if (*s == '$') // value is an argument index
{
++s;
arg_index = value;
@ -499,15 +489,15 @@ unsigned PrintfFormatter<Char, AF>::parse_header(
return arg_index;
}
template <typename Char, typename AF>
void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
template <typename Char, typename AF> void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
{
const Char *start = format_str.c_str();
const Char *s = start;
while (*s)
{
Char c = *s++;
if (c != '%') continue;
if (c != '%')
continue;
if (*s == c)
{
write(writer_, start, s);
@ -550,7 +540,7 @@ void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
if (arg.type <= Arg::LAST_NUMERIC_TYPE)
spec.align_ = ALIGN_NUMERIC;
else
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
}
// Parse length and convert the argument to the required type.
@ -703,10 +693,10 @@ inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args)
return static_cast<int>(w.size());
}
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
} // namespace fmt
} // namespace fmt
#ifdef FMT_HEADER_ONLY
# include "printf.cc"
#include "printf.cc"
#endif
#endif // FMT_PRINTF_H_
#endif // FMT_PRINTF_H_

View File

@ -14,16 +14,13 @@
#include <ctime>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code
# pragma warning(disable: 4996) // "deprecated" functions
#pragma warning(push)
#pragma warning(disable : 4702) // unreachable code
#pragma warning(disable : 4996) // "deprecated" functions
#endif
namespace fmt
{
template <typename ArgFormatter>
void format_arg(BasicFormatter<char, ArgFormatter> &f,
const char *&format_str, const std::tm &tm)
namespace fmt {
template <typename ArgFormatter> void format_arg(BasicFormatter<char, ArgFormatter> &f, const char *&format_str, const std::tm &tm)
{
if (*format_str == ':')
++format_str;
@ -60,8 +57,7 @@ void format_arg(BasicFormatter<char, ArgFormatter> &f,
format_str = end + 1;
}
namespace internal
{
namespace internal {
inline Null<> localtime_r(...)
{
return Null<>();
@ -78,7 +74,7 @@ inline Null<> gmtime_s(...)
{
return Null<>();
}
}
} // namespace internal
// Thread-safe replacement for std::localtime
inline std::tm localtime(std::time_t time)
@ -88,7 +84,10 @@ inline std::tm localtime(std::time_t time)
std::time_t time_;
std::tm tm_;
LocalTime(std::time_t t): time_(t) {}
LocalTime(std::time_t t)
: time_(t)
{
}
bool run()
{
@ -116,7 +115,8 @@ inline std::tm localtime(std::time_t time)
{
using namespace fmt::internal;
std::tm *tm = std::localtime(&time_);
if (tm) tm_ = *tm;
if (tm)
tm_ = *tm;
return tm != FMT_NULL;
}
};
@ -136,7 +136,10 @@ inline std::tm gmtime(std::time_t time)
std::time_t time_;
std::tm tm_;
GMTime(std::time_t t): time_(t) {}
GMTime(std::time_t t)
: time_(t)
{
}
bool run()
{
@ -163,7 +166,8 @@ inline std::tm gmtime(std::time_t time)
bool fallback(internal::Null<>)
{
std::tm *tm = std::gmtime(&time_);
if (tm != FMT_NULL) tm_ = *tm;
if (tm != FMT_NULL)
tm_ = *tm;
return tm != FMT_NULL;
}
};
@ -174,10 +178,10 @@ inline std::tm gmtime(std::time_t time)
FMT_THROW(fmt::FormatError("time_t value out of range"));
return std::tm();
}
} //namespace fmt
} // namespace fmt
#ifdef _MSC_VER
# pragma warning(pop)
#pragma warning(pop)
#endif
#endif // FMT_TIME_H_
#endif // FMT_TIME_H_

View File

@ -23,7 +23,7 @@
#include "bundled/printf.h"
#endif
#else //external fmtlib
#else // external fmtlib
#include <fmt/format.h>
#if defined(SPDLOG_FMT_PRINTF)
@ -31,4 +31,3 @@
#endif
#endif

View File

@ -8,10 +8,8 @@
// include external or bundled copy of fmtlib's ostream support
//
#if !defined(SPDLOG_FMT_EXTERNAL)
#include "fmt.h"
#include "bundled/ostream.h"
#include "fmt.h"
#else
#include <fmt/ostream.h>
#endif

View File

@ -7,14 +7,12 @@
#include "details/log_msg.h"
#include <vector>
#include <string>
#include <memory>
#include <string>
#include <vector>
namespace spdlog
{
namespace details
{
namespace spdlog {
namespace details {
class flag_formatter;
}
@ -22,26 +20,27 @@ class formatter
{
public:
virtual ~formatter() = default;
virtual void format(details::log_msg& msg) = 0;
virtual void format(details::log_msg &msg) = 0;
};
class pattern_formatter SPDLOG_FINAL : public formatter
{
public:
explicit pattern_formatter(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol);
pattern_formatter(const pattern_formatter&) = delete;
pattern_formatter& operator=(const pattern_formatter&) = delete;
void format(details::log_msg& msg) override;
explicit pattern_formatter(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local,
std::string eol = spdlog::details::os::default_eol);
pattern_formatter(const pattern_formatter &) = delete;
pattern_formatter &operator=(const pattern_formatter &) = delete;
void format(details::log_msg &msg) override;
private:
const std::string _eol;
const std::string _pattern;
const pattern_time_type _pattern_time;
std::vector<std::unique_ptr<details::flag_formatter>> _formatters;
std::tm get_time(details::log_msg& msg);
std::tm get_time(details::log_msg &msg);
void handle_flag(char flag);
void compile_pattern(const std::string& pattern);
void compile_pattern(const std::string &pattern);
};
}
} // namespace spdlog
#include "details/pattern_formatter_impl.h"

View File

@ -12,63 +12,61 @@
// 2. Format the message using the formatter function
// 3. Pass the formatted message to its sinks to performa the actual logging
#include "sinks/base_sink.h"
#include "common.h"
#include "sinks/base_sink.h"
#include <vector>
#include <memory>
#include <string>
#include <vector>
namespace spdlog
{
namespace spdlog {
class logger
{
public:
logger(const std::string& name, sink_ptr single_sink);
logger(const std::string& name, sinks_init_list sinks);
logger(const std::string &name, sink_ptr single_sink);
logger(const std::string &name, sinks_init_list sinks);
template <class It>
logger(std::string name, const It& begin, const It& end);
template <class It> logger(std::string name, const It &begin, const It &end);
virtual ~logger();
logger(const logger&) = delete;
logger& operator=(const logger&) = delete;
logger(const logger &) = delete;
logger &operator=(const logger &) = delete;
template <typename... Args> void log(level::level_enum lvl, const char* fmt, const Args&... args);
template <typename... Args> void log(level::level_enum lvl, const char* msg);
template <typename Arg1, typename... Args> void trace(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void debug(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void info(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void warn(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void error(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void critical(const char* fmt, const Arg1&, const Args&... args);
template <typename... Args> void log(level::level_enum lvl, const char *fmt, const Args &... args);
template <typename... Args> void log(level::level_enum lvl, const char *msg);
template <typename Arg1, typename... Args> void trace(const char *fmt, const Arg1 &, const Args &... args);
template <typename Arg1, typename... Args> void debug(const char *fmt, const Arg1 &, const Args &... args);
template <typename Arg1, typename... Args> void info(const char *fmt, const Arg1 &, const Args &... args);
template <typename Arg1, typename... Args> void warn(const char *fmt, const Arg1 &, const Args &... args);
template <typename Arg1, typename... Args> void error(const char *fmt, const Arg1 &, const Args &... args);
template <typename Arg1, typename... Args> void critical(const char *fmt, const Arg1 &, const Args &... args);
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
template <typename... Args> void log(level::level_enum lvl, const wchar_t* msg);
template <typename... Args> void log(level::level_enum lvl, const wchar_t* fmt, const Args&... args);
template <typename... Args> void trace(const wchar_t* fmt, const Args&... args);
template <typename... Args> void debug(const wchar_t* fmt, const Args&... args);
template <typename... Args> void info(const wchar_t* fmt, const Args&... args);
template <typename... Args> void warn(const wchar_t* fmt, const Args&... args);
template <typename... Args> void error(const wchar_t* fmt, const Args&... args);
template <typename... Args> void critical(const wchar_t* fmt, const Args&... args);
template <typename... Args> void log(level::level_enum lvl, const wchar_t *msg);
template <typename... Args> void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args);
template <typename... Args> void trace(const wchar_t *fmt, const Args &... args);
template <typename... Args> void debug(const wchar_t *fmt, const Args &... args);
template <typename... Args> void info(const wchar_t *fmt, const Args &... args);
template <typename... Args> void warn(const wchar_t *fmt, const Args &... args);
template <typename... Args> void error(const wchar_t *fmt, const Args &... args);
template <typename... Args> void critical(const wchar_t *fmt, const Args &... args);
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
template <typename T> void log(level::level_enum lvl, const T&);
template <typename T> void trace(const T& msg);
template <typename T> void debug(const T& msg);
template <typename T> void info(const T& msg);
template <typename T> void warn(const T& msg);
template <typename T> void error(const T& msg);
template <typename T> void critical(const T& msg);
template <typename T> void log(level::level_enum lvl, const T &);
template <typename T> void trace(const T &msg);
template <typename T> void debug(const T &msg);
template <typename T> void info(const T &msg);
template <typename T> void warn(const T &msg);
template <typename T> void error(const T &msg);
template <typename T> void critical(const T &msg);
bool should_log(level::level_enum msg_level) const;
void set_level(level::level_enum log_level);
level::level_enum level() const;
const std::string& name() const;
void set_pattern(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local);
const std::string &name() const;
void set_pattern(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local);
void set_formatter(formatter_ptr msg_formatter);
// automatically call flush() if message level >= log_level
@ -76,25 +74,25 @@ public:
virtual void flush();
const std::vector<sink_ptr>& sinks() const;
const std::vector<sink_ptr> &sinks() const;
// error handler
virtual void set_error_handler(log_err_handler err_handler);
virtual log_err_handler error_handler();
protected:
virtual void _sink_it(details::log_msg& msg);
virtual void _set_pattern(const std::string& pattern, pattern_time_type pattern_time);
virtual void _sink_it(details::log_msg &msg);
virtual void _set_pattern(const std::string &pattern, pattern_time_type pattern_time);
virtual void _set_formatter(formatter_ptr msg_formatter);
// default error handler: print the error to stderr with the max rate of 1 message/minute
virtual void _default_err_handler(const std::string &msg);
// return true if the given message level should trigger a flush
bool _should_flush_on(const details::log_msg& msg);
bool _should_flush_on(const details::log_msg &msg);
// increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
void _incr_msg_counter(details::log_msg& msg);
void _incr_msg_counter(details::log_msg &msg);
const std::string _name;
std::vector<sink_ptr> _sinks;
@ -105,6 +103,6 @@ protected:
std::atomic<time_t> _last_err_time;
std::atomic<size_t> _msg_counter;
};
}
} // namespace spdlog
#include "details/logger_impl.h"

View File

@ -7,34 +7,35 @@
#if defined(__ANDROID__)
#include "sink.h"
#include "../details/os.h"
#include "sink.h"
#include <android/log.h>
#include <chrono>
#include <mutex>
#include <string>
#include <android/log.h>
#include <thread>
#include <chrono>
#if !defined(SPDLOG_ANDROID_RETRIES)
#define SPDLOG_ANDROID_RETRIES 2
#endif
namespace spdlog
{
namespace sinks
{
namespace spdlog { namespace sinks {
/*
* Android sink (logging using __android_log_write)
* __android_log_write is thread-safe. No lock is needed.
*/
* Android sink (logging using __android_log_write)
* __android_log_write is thread-safe. No lock is needed.
*/
class android_sink : public sink
{
public:
explicit android_sink(const std::string& tag = "spdlog", bool use_raw_msg = false): _tag(tag), _use_raw_msg(use_raw_msg) {}
explicit android_sink(const std::string &tag = "spdlog", bool use_raw_msg = false)
: _tag(tag)
, _use_raw_msg(use_raw_msg)
{
}
void log(const details::log_msg& msg) override
void log(const details::log_msg &msg) override
{
const android_LogPriority priority = convert_to_android(msg.level);
const char *msg_output = (_use_raw_msg ? msg.raw.c_str() : msg.formatted.c_str());
@ -42,7 +43,7 @@ public:
// See system/core/liblog/logger_write.c for explanation of return value
int ret = __android_log_write(priority, _tag.c_str(), msg_output);
int retry_count = 0;
while ((ret == -11/*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES))
while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES))
{
details::os::sleep_for_millis(5);
ret = __android_log_write(priority, _tag.c_str(), msg_output);
@ -55,14 +56,12 @@ public:
}
}
void flush() override
{
}
void flush() override {}
private:
static android_LogPriority convert_to_android(spdlog::level::level_enum level)
{
switch(level)
switch (level)
{
case spdlog::level::trace:
return ANDROID_LOG_VERBOSE;
@ -85,7 +84,6 @@ private:
bool _use_raw_msg;
};
}
}
}} // namespace spdlog::sinks
#endif

View File

@ -5,28 +5,25 @@
#pragma once
#include "base_sink.h"
#include "../common.h"
#include "../details/os.h"
#include "base_sink.h"
#include <string>
#include <unordered_map>
namespace spdlog
{
namespace sinks
{
namespace spdlog { namespace sinks {
/**
* This sink prefixes the output with an ANSI escape sequence color code depending on the severity
* of the message.
* If no color terminal detected, omit the escape codes.
*/
template <class Mutex>
class ansicolor_sink : public base_sink<Mutex>
template <class Mutex> class ansicolor_sink : public base_sink<Mutex>
{
public:
explicit ansicolor_sink(FILE* file) : target_file_(file)
explicit ansicolor_sink(FILE *file)
: target_file_(file)
{
should_do_colors_ = details::os::in_terminal(file) && details::os::is_color_terminal();
colors_[level::trace] = cyan;
@ -43,7 +40,7 @@ public:
_flush();
}
void set_color(level::level_enum color_level, const std::string& color)
void set_color(level::level_enum color_level, const std::string &color)
{
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
colors_[color_level] = color;
@ -80,13 +77,13 @@ public:
const std::string on_white = "\033[47m";
protected:
void _sink_it(const details::log_msg& msg) override
void _sink_it(const details::log_msg &msg) override
{
// Wrap the originally formatted message in color codes.
// If color is not supported in the terminal, log as is instead.
if (should_do_colors_)
{
const std::string& prefix = colors_[msg.level];
const std::string &prefix = colors_[msg.level];
fwrite(prefix.data(), sizeof(char), prefix.size(), target_file_);
fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), target_file_);
fwrite(reset.data(), sizeof(char), reset.size(), target_file_);
@ -104,34 +101,33 @@ protected:
fflush(target_file_);
}
FILE* target_file_;
FILE *target_file_;
bool should_do_colors_;
std::unordered_map<level::level_enum, std::string, level::level_hasher> colors_;
};
template<class Mutex>
class ansicolor_stdout_sink: public ansicolor_sink<Mutex>
template <class Mutex> class ansicolor_stdout_sink : public ansicolor_sink<Mutex>
{
public:
ansicolor_stdout_sink(): ansicolor_sink<Mutex>(stdout)
{}
ansicolor_stdout_sink()
: ansicolor_sink<Mutex>(stdout)
{
}
};
using ansicolor_stdout_sink_mt = ansicolor_stdout_sink<std::mutex>;
using ansicolor_stdout_sink_st = ansicolor_stdout_sink<details::null_mutex>;
template<class Mutex>
class ansicolor_stderr_sink: public ansicolor_sink<Mutex>
template <class Mutex> class ansicolor_stderr_sink : public ansicolor_sink<Mutex>
{
public:
ansicolor_stderr_sink(): ansicolor_sink<Mutex>(stderr)
{}
ansicolor_stderr_sink()
: ansicolor_sink<Mutex>(stderr)
{
}
};
using ansicolor_stderr_sink_mt = ansicolor_stderr_sink<std::mutex>;
using ansicolor_stderr_sink_st = ansicolor_stderr_sink<details::null_mutex>;
} // namespace sinks
} // namespace spdlog
}} // namespace spdlog::sinks

View File

@ -10,27 +10,23 @@
// all locking is taken care of here so no locking needed by the implementers..
//
#include "sink.h"
#include "../formatter.h"
#include "../common.h"
#include "../details/log_msg.h"
#include "../formatter.h"
#include "sink.h"
#include <mutex>
namespace spdlog
{
namespace sinks
{
template<class Mutex>
class base_sink : public sink
namespace spdlog { namespace sinks {
template <class Mutex> class base_sink : public sink
{
public:
base_sink() = default;
base_sink(const base_sink&) = delete;
base_sink& operator=(const base_sink&) = delete;
base_sink(const base_sink &) = delete;
base_sink &operator=(const base_sink &) = delete;
void log(const details::log_msg& msg) SPDLOG_FINAL override
void log(const details::log_msg &msg) SPDLOG_FINAL override
{
std::lock_guard<Mutex> lock(_mutex);
_sink_it(msg);
@ -43,9 +39,8 @@ public:
}
protected:
virtual void _sink_it(const details::log_msg& msg) = 0;
virtual void _sink_it(const details::log_msg &msg) = 0;
virtual void _flush() = 0;
Mutex _mutex;
};
}
}
}} // namespace spdlog::sinks

View File

@ -11,32 +11,31 @@
#include "sink.h"
#include <algorithm>
#include <mutex>
#include <memory>
#include <mutex>
#include <vector>
// Distribution sink (mux). Stores a vector of sinks which get called when log is called
namespace spdlog
{
namespace sinks
{
template<class Mutex>
class dist_sink : public base_sink<Mutex>
namespace spdlog { namespace sinks {
template <class Mutex> class dist_sink : public base_sink<Mutex>
{
public:
explicit dist_sink() :_sinks() {}
dist_sink(const dist_sink&) = delete;
dist_sink& operator=(const dist_sink&) = delete;
explicit dist_sink()
: _sinks()
{
}
dist_sink(const dist_sink &) = delete;
dist_sink &operator=(const dist_sink &) = delete;
protected:
std::vector<std::shared_ptr<sink>> _sinks;
void _sink_it(const details::log_msg& msg) override
void _sink_it(const details::log_msg &msg) override
{
for (auto &sink : _sinks)
{
if( sink->should_log( msg.level))
if (sink->should_log(msg.level))
{
sink->log(msg);
}
@ -66,5 +65,4 @@ public:
using dist_sink_mt = dist_sink<std::mutex>;
using dist_sink_st = dist_sink<details::null_mutex>;
}
}
}} // namespace spdlog::sinks

View File

@ -5,31 +5,28 @@
#pragma once
#include "base_sink.h"
#include "../details/null_mutex.h"
#include "../details/file_helper.h"
#include "../details/null_mutex.h"
#include "../fmt/fmt.h"
#include "base_sink.h"
#include <algorithm>
#include <cerrno>
#include <chrono>
#include <cstdio>
#include <ctime>
#include <mutex>
#include <string>
#include <cerrno>
namespace spdlog
{
namespace sinks
{
namespace spdlog { namespace sinks {
/*
* Trivial file sink with single file as target
*/
template <class Mutex>
class simple_file_sink SPDLOG_FINAL : public base_sink<Mutex>
template <class Mutex> class simple_file_sink SPDLOG_FINAL : public base_sink<Mutex>
{
public:
explicit simple_file_sink(const filename_t &filename, bool truncate = false):_force_flush(false)
explicit simple_file_sink(const filename_t &filename, bool truncate = false)
: _force_flush(false)
{
_file_helper.open(filename, truncate);
}
@ -40,10 +37,10 @@ public:
}
protected:
void _sink_it(const details::log_msg& msg) override
void _sink_it(const details::log_msg &msg) override
{
_file_helper.write(msg);
if(_force_flush)
if (_force_flush)
_file_helper.flush();
}
@ -63,23 +60,21 @@ using simple_file_sink_st = simple_file_sink<details::null_mutex>;
/*
* Rotating file sink based on size
*/
template <class Mutex>
class rotating_file_sink SPDLOG_FINAL : public base_sink<Mutex>
template <class Mutex> class rotating_file_sink SPDLOG_FINAL : public base_sink<Mutex>
{
public:
rotating_file_sink(filename_t base_filename,
std::size_t max_size, std::size_t max_files) :
_base_filename(std::move(base_filename)),
_max_size(max_size),
_max_files(max_files)
rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files)
: _base_filename(std::move(base_filename))
, _max_size(max_size)
, _max_files(max_files)
{
_file_helper.open(calc_filename(_base_filename, 0));
_current_size = _file_helper.size(); //expensive. called only once
_current_size = _file_helper.size(); // expensive. called only once
}
// calc filename according to index and file extension if exists.
// e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
static filename_t calc_filename(const filename_t& filename, std::size_t index)
static filename_t calc_filename(const filename_t &filename, std::size_t index)
{
typename std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
if (index != 0u)
@ -96,7 +91,7 @@ public:
}
protected:
void _sink_it(const details::log_msg& msg) override
void _sink_it(const details::log_msg &msg) override
{
_current_size += msg.formatted.size();
if (_current_size > _max_size)
@ -158,13 +153,14 @@ using rotating_file_sink_st = rotating_file_sink<details::null_mutex>;
struct default_daily_file_name_calculator
{
// Create filename for the form filename.YYYY-MM-DD_hh-mm.ext
static filename_t calc_filename(const filename_t& filename)
static filename_t calc_filename(const filename_t &filename)
{
std::tm tm = spdlog::details::os::localtime();
filename_t basename, ext;
std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename);
std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, ext);
w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, ext);
return w.str();
}
};
@ -175,7 +171,7 @@ struct default_daily_file_name_calculator
struct dateonly_daily_file_name_calculator
{
// Create filename for the form basename.YYYY-MM-DD
static filename_t calc_filename(const filename_t& filename)
static filename_t calc_filename(const filename_t &filename)
{
std::tm tm = spdlog::details::os::localtime();
filename_t basename, ext;
@ -189,18 +185,14 @@ struct dateonly_daily_file_name_calculator
/*
* Rotating file sink based on date. rotates at midnight
*/
template<class Mutex, class FileNameCalc = default_daily_file_name_calculator>
class daily_file_sink SPDLOG_FINAL :public base_sink < Mutex >
template <class Mutex, class FileNameCalc = default_daily_file_name_calculator> class daily_file_sink SPDLOG_FINAL : public base_sink<Mutex>
{
public:
//create daily file sink which rotates on given time
daily_file_sink(
filename_t base_filename,
int rotation_hour,
int rotation_minute) :
_base_filename(std::move(base_filename)),
_rotation_h(rotation_hour),
_rotation_m(rotation_minute)
// create daily file sink which rotates on given time
daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute)
: _base_filename(std::move(base_filename))
, _rotation_h(rotation_hour)
, _rotation_m(rotation_minute)
{
if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
@ -208,9 +200,8 @@ public:
_file_helper.open(FileNameCalc::calc_filename(_base_filename));
}
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() >= _rotation_tp)
{
@ -239,7 +230,7 @@ private:
{
return rotation_time;
}
return{ rotation_time + std::chrono::hours(24) };
return {rotation_time + std::chrono::hours(24)};
}
filename_t _base_filename;
@ -252,5 +243,4 @@ private:
using daily_file_sink_mt = daily_file_sink<std::mutex>;
using daily_file_sink_st = daily_file_sink<details::null_mutex>;
}
}
}} // namespace spdlog::sinks

View File

@ -7,43 +7,35 @@
#if defined(_WIN32)
#include "base_sink.h"
#include "../details/null_mutex.h"
#include "base_sink.h"
#include <winbase.h>
#include <mutex>
#include <string>
namespace spdlog
{
namespace sinks
{
namespace spdlog { namespace sinks {
/*
* MSVC sink (logging using OutputDebugStringA)
*/
template<class Mutex>
class msvc_sink : public base_sink<Mutex>
* MSVC sink (logging using OutputDebugStringA)
*/
template <class Mutex> class msvc_sink : public base_sink<Mutex>
{
public:
explicit msvc_sink()
{
}
explicit msvc_sink() {}
protected:
void _sink_it(const details::log_msg& msg) override
void _sink_it(const details::log_msg &msg) override
{
OutputDebugStringA(msg.formatted.c_str());
}
void _flush() override
{}
void _flush() override {}
};
using msvc_sink_mt = msvc_sink<std::mutex>;
using msvc_sink_st = msvc_sink<details::null_mutex>;
}
}
}} // namespace spdlog::sinks
#endif

View File

@ -5,31 +5,22 @@
#pragma once
#include "base_sink.h"
#include "../details/null_mutex.h"
#include "base_sink.h"
#include <mutex>
namespace spdlog
{
namespace sinks
{
namespace spdlog { namespace sinks {
template <class Mutex>
class null_sink : public base_sink<Mutex>
template <class Mutex> class null_sink : public base_sink<Mutex>
{
protected:
void _sink_it(const details::log_msg&) override
{}
void _flush() override
{}
void _sink_it(const details::log_msg &) override {}
void _flush() override {}
};
using null_sink_mt = null_sink<details::null_mutex>;
using null_sink_st = null_sink<details::null_mutex>;
}
}
}} // namespace spdlog::sinks

View File

@ -8,23 +8,23 @@
#include "../details/null_mutex.h"
#include "base_sink.h"
#include <ostream>
#include <mutex>
#include <ostream>
namespace spdlog
{
namespace sinks
{
template<class Mutex>
class ostream_sink : public base_sink<Mutex>
namespace spdlog { namespace sinks {
template <class Mutex> class ostream_sink : public base_sink<Mutex>
{
public:
explicit ostream_sink(std::ostream& os, bool force_flush=false) :_ostream(os), _force_flush(force_flush) {}
ostream_sink(const ostream_sink&) = delete;
ostream_sink& operator=(const ostream_sink&) = delete;
explicit ostream_sink(std::ostream &os, bool force_flush = false)
: _ostream(os)
, _force_flush(force_flush)
{
}
ostream_sink(const ostream_sink &) = delete;
ostream_sink &operator=(const ostream_sink &) = delete;
protected:
void _sink_it(const details::log_msg& msg) override
void _sink_it(const details::log_msg &msg) override
{
_ostream.write(msg.formatted.data(), msg.formatted.size());
if (_force_flush)
@ -36,12 +36,11 @@ protected:
_ostream.flush();
}
std::ostream& _ostream;
std::ostream &_ostream;
bool _force_flush;
};
using ostream_sink_mt = ostream_sink<std::mutex>;
using ostream_sink_st = ostream_sink<details::null_mutex>;
}
}
}} // namespace spdlog::sinks

View File

@ -7,16 +7,13 @@
#include "../details/log_msg.h"
namespace spdlog
{
namespace sinks
{
namespace spdlog { namespace sinks {
class sink
{
public:
virtual ~sink() = default;
virtual void log(const details::log_msg& msg) = 0;
virtual void log(const details::log_msg &msg) = 0;
virtual void flush() = 0;
bool should_log(level::level_enum msg_level) const;
@ -24,7 +21,7 @@ public:
level::level_enum level() const;
private:
level_t _level{ level::trace };
level_t _level{level::trace};
};
inline bool sink::should_log(level::level_enum msg_level) const
@ -42,5 +39,4 @@ inline level::level_enum sink::level() const
return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
}
}
}
}} // namespace spdlog::sinks

View File

@ -12,13 +12,9 @@
#include <memory>
#include <mutex>
namespace spdlog
{
namespace sinks
{
namespace spdlog { namespace sinks {
template <class Mutex>
class stdout_sink SPDLOG_FINAL : public base_sink<Mutex>
template <class Mutex> class stdout_sink SPDLOG_FINAL : public base_sink<Mutex>
{
using MyType = stdout_sink<Mutex>;
@ -32,7 +28,7 @@ public:
}
protected:
void _sink_it(const details::log_msg& msg) override
void _sink_it(const details::log_msg &msg) override
{
fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout);
_flush();
@ -47,8 +43,7 @@ protected:
using stdout_sink_mt = stdout_sink<std::mutex>;
using stdout_sink_st = stdout_sink<details::null_mutex>;
template <class Mutex>
class stderr_sink SPDLOG_FINAL : public base_sink<Mutex>
template <class Mutex> class stderr_sink SPDLOG_FINAL : public base_sink<Mutex>
{
using MyType = stderr_sink<Mutex>;
@ -62,7 +57,7 @@ public:
}
protected:
void _sink_it(const details::log_msg& msg) override
void _sink_it(const details::log_msg &msg) override
{
fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stderr);
_flush();
@ -77,5 +72,4 @@ protected:
using stderr_sink_mt = stderr_sink<std::mutex>;
using stderr_sink_st = stderr_sink<details::null_mutex>;
}
}
}} // namespace spdlog::sinks

View File

@ -9,18 +9,14 @@
#ifdef SPDLOG_ENABLE_SYSLOG
#include "sink.h"
#include "../details/log_msg.h"
#include "sink.h"
#include <array>
#include <string>
#include <syslog.h>
namespace spdlog
{
namespace sinks
{
namespace spdlog { namespace sinks {
/**
* Sink that write to syslog using the `syscall()` library call.
*
@ -30,8 +26,8 @@ class syslog_sink : public sink
{
public:
//
syslog_sink(const std::string& ident = "", int syslog_option=0, int syslog_facility=LOG_USER):
_ident(ident)
syslog_sink(const std::string &ident = "", int syslog_option = 0, int syslog_facility = LOG_USER)
: _ident(ident)
{
_priorities[static_cast<size_t>(level::trace)] = LOG_DEBUG;
_priorities[static_cast<size_t>(level::debug)] = LOG_DEBUG;
@ -41,8 +37,8 @@ public:
_priorities[static_cast<size_t>(level::critical)] = LOG_CRIT;
_priorities[static_cast<size_t>(level::off)] = LOG_INFO;
//set ident to be program name if empty
::openlog(_ident.empty()? nullptr:_ident.c_str(), syslog_option, syslog_facility);
// set ident to be program name if empty
::openlog(_ident.empty() ? nullptr : _ident.c_str(), syslog_option, syslog_facility);
}
~syslog_sink() override
@ -50,22 +46,19 @@ public:
::closelog();
}
syslog_sink(const syslog_sink&) = delete;
syslog_sink& operator=(const syslog_sink&) = delete;
syslog_sink(const syslog_sink &) = delete;
syslog_sink &operator=(const syslog_sink &) = delete;
void log(const details::log_msg &msg) override
{
::syslog(syslog_prio_from_level(msg), "%s", msg.raw.str().c_str());
}
void flush() override
{
}
void flush() override {}
private:
std::array<int, 7> _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;
//
@ -76,7 +69,6 @@ private:
return _priorities[static_cast<size_t>(msg.level)];
}
};
}
}
}} // namespace spdlog::sinks
#endif

View File

@ -5,24 +5,20 @@
#pragma once
#include "base_sink.h"
#include "../details/null_mutex.h"
#include "../common.h"
#include "../details/null_mutex.h"
#include "base_sink.h"
#include <mutex>
#include <string>
#include <unordered_map>
#include <wincon.h>
namespace spdlog
{
namespace sinks
{
namespace spdlog { namespace sinks {
/*
* Windows color console sink. Uses WriteConsoleA to write to the console with colors
*/
template <class Mutex>
class wincolor_sink : public base_sink<Mutex>
template <class Mutex> class wincolor_sink : public base_sink<Mutex>
{
public:
const WORD BOLD = FOREGROUND_INTENSITY;
@ -31,13 +27,14 @@ public:
const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN;
wincolor_sink(HANDLE std_handle): out_handle_(std_handle)
wincolor_sink(HANDLE std_handle)
: out_handle_(std_handle)
{
colors_[level::trace] = CYAN;
colors_[level::debug] = CYAN;
colors_[level::info] = WHITE | BOLD;
colors_[level::warn] = YELLOW | BOLD;
colors_[level::err] = RED | BOLD; // red bold
colors_[level::err] = RED | BOLD; // red bold
colors_[level::critical] = BACKGROUND_RED | WHITE | BOLD; // white bold on red background
colors_[level::off] = 0;
}
@ -47,8 +44,8 @@ public:
this->flush();
}
wincolor_sink(const wincolor_sink& other) = delete;
wincolor_sink& operator=(const wincolor_sink& other) = delete;
wincolor_sink(const wincolor_sink &other) = delete;
wincolor_sink &operator=(const wincolor_sink &other) = delete;
// change the color for the given level
void set_color(level::level_enum level, WORD color)
@ -58,12 +55,12 @@ public:
}
protected:
void _sink_it(const details::log_msg& msg) override
void _sink_it(const details::log_msg &msg) override
{
auto color = colors_[msg.level];
auto orig_attribs = set_console_attribs(color);
WriteConsoleA(out_handle_, msg.formatted.data(), static_cast<DWORD>(msg.formatted.size()), nullptr, nullptr);
SetConsoleTextAttribute(out_handle_, orig_attribs); //reset to orig colors
SetConsoleTextAttribute(out_handle_, orig_attribs); // reset to orig colors
}
void _flush() override
@ -85,19 +82,20 @@ private:
back_color &= static_cast<WORD>(~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY));
// keep the background color unchanged
SetConsoleTextAttribute(out_handle_, attribs | back_color);
return orig_buffer_info.wAttributes; //return orig attribs
return orig_buffer_info.wAttributes; // return orig attribs
}
};
//
// windows color console to stdout
//
template <class Mutex>
class wincolor_stdout_sink : public wincolor_sink<Mutex>
template <class Mutex> class wincolor_stdout_sink : public wincolor_sink<Mutex>
{
public:
wincolor_stdout_sink() : wincolor_sink<Mutex>(GetStdHandle(STD_OUTPUT_HANDLE))
{}
wincolor_stdout_sink()
: wincolor_sink<Mutex>(GetStdHandle(STD_OUTPUT_HANDLE))
{
}
};
using wincolor_stdout_sink_mt = wincolor_stdout_sink<std::mutex>;
@ -106,16 +104,16 @@ using wincolor_stdout_sink_st = wincolor_stdout_sink<details::null_mutex>;
//
// windows color console to stderr
//
template <class Mutex>
class wincolor_stderr_sink : public wincolor_sink<Mutex>
template <class Mutex> class wincolor_stderr_sink : public wincolor_sink<Mutex>
{
public:
wincolor_stderr_sink() : wincolor_sink<Mutex>(GetStdHandle(STD_ERROR_HANDLE))
{}
wincolor_stderr_sink()
: wincolor_sink<Mutex>(GetStdHandle(STD_ERROR_HANDLE))
{
}
};
using wincolor_stderr_sink_mt = wincolor_stderr_sink<std::mutex>;
using wincolor_stderr_sink_st = wincolor_stderr_sink<details::null_mutex>;
}
}
}} // namespace spdlog::sinks

View File

@ -9,21 +9,16 @@
#include "msvc_sink.h"
namespace spdlog
{
namespace sinks
{
namespace spdlog { namespace sinks {
/*
* Windows debug sink (logging using OutputDebugStringA, synonym for msvc_sink)
*/
template <class Mutex>
using windebug_sink = msvc_sink<Mutex>;
* Windows debug sink (logging using OutputDebugStringA, synonym for msvc_sink)
*/
template <class Mutex> using windebug_sink = msvc_sink<Mutex>;
using windebug_sink_mt = msvc_sink_mt;
using windebug_sink_st = msvc_sink_st;
}
}
}} // namespace spdlog::sinks
#endif

View File

@ -7,30 +7,27 @@
#pragma once
#include "common.h"
#include "logger.h"
#include <memory>
#include <functional>
#include <chrono>
#include <functional>
#include <memory>
#include <string>
namespace spdlog
{
namespace spdlog {
//
// Return an existing logger or nullptr if a logger with such name doesn't exist.
// example: spdlog::get("my_logger")->info("hello {}", "world");
//
std::shared_ptr<logger> get(const std::string& name);
std::shared_ptr<logger> get(const std::string &name);
//
// Set global formatting
// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v");
//
void set_pattern(const std::string& format_string);
void set_pattern(const std::string &format_string);
void set_formatter(formatter_ptr f);
//
@ -64,80 +61,93 @@ void set_error_handler(log_err_handler handler);
// worker_teardown_cb (optional):
// callback function that will be called in worker thread upon exit
//
void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr);
void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
// Turn off async mode
void set_sync_mode();
//
// Create and register multi/single threaded basic file logger.
// Basic logger simply writes to given file without any limitations or rotations.
//
std::shared_ptr<logger> basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate = false);
std::shared_ptr<logger> basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate = false);
std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false);
std::shared_ptr<logger> basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false);
//
// Create and register multi/single threaded rotating file logger
//
std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files);
std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files);
std::shared_ptr<logger> rotating_logger_mt(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files);
std::shared_ptr<logger> rotating_logger_st(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files);
//
// Create file logger which creates new file on the given time (default in midnight):
//
std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0);
std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0);
std::shared_ptr<logger> daily_logger_mt(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0);
std::shared_ptr<logger> daily_logger_st(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0);
//
// Create and register stdout/stderr loggers
//
std::shared_ptr<logger> stdout_logger_mt(const std::string& logger_name);
std::shared_ptr<logger> stdout_logger_st(const std::string& logger_name);
std::shared_ptr<logger> stderr_logger_mt(const std::string& logger_name);
std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name);
std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name);
std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name);
std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name);
std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name);
//
// Create and register colored stdout/stderr loggers
//
std::shared_ptr<logger> stdout_color_mt(const std::string& logger_name);
std::shared_ptr<logger> stdout_color_st(const std::string& logger_name);
std::shared_ptr<logger> stderr_color_mt(const std::string& logger_name);
std::shared_ptr<logger> stderr_color_st(const std::string& logger_name);
std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name);
std::shared_ptr<logger> stdout_color_st(const std::string &logger_name);
std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name);
std::shared_ptr<logger> stderr_color_st(const std::string &logger_name);
//
// Create and register a syslog logger
//
#ifdef SPDLOG_ENABLE_SYSLOG
std::shared_ptr<logger> syslog_logger(const std::string& logger_name, const std::string& ident = "", int syslog_option = 0, int syslog_facilty = (1<<3));
std::shared_ptr<logger> syslog_logger(
const std::string &logger_name, const std::string &ident = "", int syslog_option = 0, int syslog_facilty = (1 << 3));
#endif
#if defined(__ANDROID__)
std::shared_ptr<logger> android_logger(const std::string& logger_name, const std::string& tag = "spdlog");
std::shared_ptr<logger> android_logger(const std::string &logger_name, const std::string &tag = "spdlog");
#endif
// Create and register a logger with a single sink
std::shared_ptr<logger> create(const std::string& logger_name, const sink_ptr& sink);
std::shared_ptr<logger> create(const std::string &logger_name, const sink_ptr &sink);
// Create and register a logger with multiple sinks
std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks);
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, sinks_init_list sinks);
template <class It> std::shared_ptr<logger> create(const std::string &logger_name, const It &sinks_begin, const It &sinks_end);
// Create and register a logger with templated sink type
// Example:
// spdlog::create<daily_file_sink_st>("mylog", "dailylog_filename");
template <typename Sink, typename... Args>
std::shared_ptr<spdlog::logger> create(const std::string& logger_name, Args... args);
template <typename Sink, typename... Args> std::shared_ptr<spdlog::logger> create(const std::string &logger_name, Args... args);
// Create and register an async logger with a single sink
std::shared_ptr<logger> create_async(const std::string& logger_name, const sink_ptr& sink, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr);
std::shared_ptr<logger> create_async(const std::string &logger_name, const sink_ptr &sink, size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
// Create and register an async logger with multiple sinks
std::shared_ptr<logger> create_async(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr);
template<class It>
std::shared_ptr<logger> create_async(const std::string& logger_name, const It& sinks_begin, const It& sinks_end, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr);
std::shared_ptr<logger> create_async(const std::string &logger_name, sinks_init_list sinks, size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
template <class It>
std::shared_ptr<logger> create_async(const std::string &logger_name, const It &sinks_begin, const It &sinks_end, size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
// Register the given logger with the given name
void register_logger(std::shared_ptr<logger> logger);
@ -153,7 +163,6 @@ void drop(const std::string &name);
// Drop all references from the registry
void drop_all();
///////////////////////////////////////////////////////////////////////////////
//
// Trace & Debug can be switched on/off at compile time for zero cost debug statements.
@ -168,23 +177,23 @@ void drop_all();
///////////////////////////////////////////////////////////////////////////////
#ifdef SPDLOG_TRACE_ON
# define SPDLOG_STR_H(x) #x
# define SPDLOG_STR_HELPER(x) SPDLOG_STR_H(x)
# ifdef _MSC_VER
# define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ "(" SPDLOG_STR_HELPER(__LINE__) ") ] " __VA_ARGS__)
# else
# define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ ":" SPDLOG_STR_HELPER(__LINE__) " ] " __VA_ARGS__)
# endif
#define SPDLOG_STR_H(x) #x
#define SPDLOG_STR_HELPER(x) SPDLOG_STR_H(x)
#ifdef _MSC_VER
#define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ "(" SPDLOG_STR_HELPER(__LINE__) ") ] " __VA_ARGS__)
#else
# define SPDLOG_TRACE(logger, ...) (void)0
#define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ ":" SPDLOG_STR_HELPER(__LINE__) " ] " __VA_ARGS__)
#endif
#else
#define SPDLOG_TRACE(logger, ...) (void)0
#endif
#ifdef SPDLOG_DEBUG_ON
# define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__)
#define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__)
#else
# define SPDLOG_DEBUG(logger, ...) (void)0
#define SPDLOG_DEBUG(logger, ...) (void)0
#endif
}
} // namespace spdlog
#include "details/spdlog_impl.h"

View File

@ -11,7 +11,6 @@
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used.
// This clock is less accurate - can be off by dozens of millis - depending on the kernel HZ.
@ -20,7 +19,6 @@
// #define SPDLOG_CLOCK_COARSE
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment if date/time logging is not needed and never appear in the log pattern.
// This will prevent spdlog from querying the clock on each log call.
@ -31,7 +29,6 @@
// #define SPDLOG_NO_DATETIME
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment if thread id logging is not needed (i.e. no %t in the log pattern).
// This will prevent spdlog from querying the thread id on each log call.
@ -41,7 +38,6 @@
// #define SPDLOG_NO_THREAD_ID
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to prevent spdlog from caching thread ids in thread local storage.
// By default spdlog saves thread ids in tls to gain a few micros for each call.
@ -51,7 +47,6 @@
// #define SPDLOG_DISABLE_TID_CACHING
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment if logger name logging is not needed.
// This will prevent spdlog from copying the logger name on each log call.
@ -66,7 +61,6 @@
// #define SPDLOG_TRACE_ON
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to avoid locking in the registry operations (spdlog::get(), spdlog::drop() spdlog::register()).
// Use only if your code never modifies concurrently the registry.
@ -75,7 +69,6 @@
// #define SPDLOG_NO_REGISTRY_MUTEX
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to avoid spdlog's usage of atomic log levels
// Use only if your code never modifies a logger's log levels concurrently by different threads.
@ -83,21 +76,18 @@
// #define SPDLOG_NO_ATOMIC_LEVELS
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to enable usage of wchar_t for file names on Windows.
//
// #define SPDLOG_WCHAR_FILENAMES
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to override default eol ("\n" or "\r\n" under Linux/Windows)
//
// #define SPDLOG_EOL ";-)\n"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to use your own copy of the fmt library instead of spdlog's copy.
// In this case spdlog will try to include <fmt/format.h> so set your -I flag accordingly.
@ -105,7 +95,6 @@
// #define SPDLOG_FMT_EXTERNAL
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to use printf-style messages in your logs instead of the usual
// format-style used by default.
@ -113,28 +102,24 @@
// #define SPDLOG_FMT_PRINTF
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to enable syslog (disabled by default)
//
// #define SPDLOG_ENABLE_SYSLOG
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to enable wchar_t support (convert to utf8)
//
// #define SPDLOG_WCHAR_TO_UTF8_SUPPORT
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to prevent child processes from inheriting log file descriptors
//
// #define SPDLOG_PREVENT_CHILD_FD
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment if your compiler doesn't support the "final" keyword.
// The final keyword allows more optimizations in release
@ -144,7 +129,6 @@
// #define SPDLOG_NO_FINAL
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to enable message counting feature.
// Use the %i in the logger pattern to display log message sequence id.
@ -152,7 +136,6 @@
// #define SPDLOG_ENABLE_MESSAGE_COUNTER
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to customize level names (e.g. "MT TRACE")
//

View File

@ -1,22 +1,18 @@
/*
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
#include "includes.h"
#include<iostream>
#include <iostream>
class failing_sink: public spdlog::sinks::sink
class failing_sink : public spdlog::sinks::sink
{
void log(const spdlog::details::log_msg& msg) override
void log(const spdlog::details::log_msg &msg) override
{
throw std::runtime_error("some error happened during log");
}
void flush() override
{}
void flush() override {}
};
TEST_CASE("default_error_handler", "[errors]]")
@ -39,21 +35,16 @@ TEST_CASE("default_error_handler", "[errors]]")
REQUIRE(count_lines(filename) == 1);
}
struct custom_ex
{};
{
};
TEST_CASE("custom_error_handler", "[errors]]")
{
prepare_logdir();
std::string filename = "logs/simple_log.txt";
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename, true);
logger->flush_on(spdlog::level::info);
logger->set_error_handler([=](const std::string& msg)
{
throw custom_ex();
});
logger->set_error_handler([=](const std::string &msg) { throw custom_ex(); });
logger->info("Good message #1");
#if !defined(SPDLOG_FMT_PRINTF)
REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex);
@ -68,10 +59,7 @@ TEST_CASE("default_error_handler2", "[errors]]")
{
auto logger = spdlog::create<failing_sink>("failed_logger");
logger->set_error_handler([=](const std::string& msg)
{
throw custom_ex();
});
logger->set_error_handler([=](const std::string &msg) { throw custom_ex(); });
REQUIRE_THROWS_AS(logger->info("Some message"), custom_ex);
}
@ -83,10 +71,10 @@ TEST_CASE("async_error_handler", "[errors]]")
std::string filename = "logs/simple_async_log.txt";
{
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename, true);
logger->set_error_handler([=](const std::string& msg)
{
logger->set_error_handler([=](const std::string &msg) {
std::ofstream ofs("logs/custom_err.txt");
if (!ofs) throw std::runtime_error("Failed open logs/custom_err.txt");
if (!ofs)
throw std::runtime_error("Failed open logs/custom_err.txt");
ofs << err_msg;
});
logger->info("Good message #1");
@ -96,7 +84,7 @@ TEST_CASE("async_error_handler", "[errors]]")
logger->info("Bad format msg %s %s", "xxx");
#endif
logger->info("Good message #2");
spdlog::drop("logger"); //force logger to drain the queue and shutdown
spdlog::drop("logger"); // force logger to drain the queue and shutdown
spdlog::set_sync_mode();
}
REQUIRE(count_lines(filename) == 2);
@ -111,14 +99,14 @@ TEST_CASE("async_error_handler2", "[errors]]")
spdlog::set_async_mode(128);
{
auto logger = spdlog::create<failing_sink>("failed_logger");
logger->set_error_handler([=](const std::string& msg)
{
logger->set_error_handler([=](const std::string &msg) {
std::ofstream ofs("logs/custom_err2.txt");
if (!ofs) throw std::runtime_error("Failed open logs/custom_err2.txt");
if (!ofs)
throw std::runtime_error("Failed open logs/custom_err2.txt");
ofs << err_msg;
});
logger->info("Hello failure");
spdlog::drop("failed_logger"); //force logger to drain the queue and shutdown
spdlog::drop("failed_logger"); // force logger to drain the queue and shutdown
spdlog::set_sync_mode();
}

View File

@ -1,10 +1,10 @@
/*
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
#include "includes.h"
using spdlog::details::log_msg;
using spdlog::details::file_helper;
using spdlog::details::log_msg;
static const std::string target_filename = "logs/file_helper_test.txt";
@ -70,7 +70,7 @@ TEST_CASE("file_helper_reopen2", "[file_helper::reopen(false)]]")
REQUIRE(helper.size() == expected_size);
}
static void test_split_ext(const char* fname, const char* expect_base, const char* expect_ext)
static void test_split_ext(const char *fname, const char *expect_base, const char *expect_ext)
{
spdlog::filename_t filename(fname);
spdlog::filename_t expected_base(expect_base);

View File

@ -3,7 +3,6 @@
*/
#include "includes.h"
TEST_CASE("simple_file_logger", "[simple_logger]]")
{
prepare_logdir();
@ -24,7 +23,6 @@ TEST_CASE("simple_file_logger", "[simple_logger]]")
REQUIRE(count_lines(filename) == 2);
}
TEST_CASE("flush_on", "[flush_on]]")
{
prepare_logdir();
@ -69,7 +67,6 @@ TEST_CASE("rotating_file_logger1", "[rotating_logger]]")
REQUIRE(count_lines(filename) == 10);
}
TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
{
prepare_logdir();
@ -96,11 +93,10 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
REQUIRE(get_filesize(filename1) <= 1024);
}
TEST_CASE("daily_logger", "[daily_logger]]")
{
prepare_logdir();
//calculate filename (time based)
// calculate filename (time based)
std::string basename = "logs/daily_log";
std::tm tm = spdlog::details::os::localtime();
fmt::MemoryWriter w;
@ -121,15 +117,12 @@ TEST_CASE("daily_logger", "[daily_logger]]")
REQUIRE(count_lines(filename) == 10);
}
TEST_CASE("daily_logger with dateonly calculator", "[daily_logger_dateonly]]")
{
using sink_type = spdlog::sinks::daily_file_sink<
std::mutex,
spdlog::sinks::dateonly_daily_file_name_calculator>;
using sink_type = spdlog::sinks::daily_file_sink<std::mutex, spdlog::sinks::dateonly_daily_file_name_calculator>;
prepare_logdir();
//calculate filename (time based)
// calculate filename (time based)
std::string basename = "logs/daily_dateonly";
std::tm tm = spdlog::details::os::localtime();
fmt::MemoryWriter w;
@ -151,7 +144,7 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger_dateonly]]")
struct custom_daily_file_name_calculator
{
static spdlog::filename_t calc_filename(const spdlog::filename_t& basename)
static spdlog::filename_t calc_filename(const spdlog::filename_t &basename)
{
std::tm tm = spdlog::details::os::localtime();
fmt::MemoryWriter w;
@ -162,12 +155,10 @@ struct custom_daily_file_name_calculator
TEST_CASE("daily_logger with custom calculator", "[daily_logger_custom]]")
{
using sink_type = spdlog::sinks::daily_file_sink<
std::mutex,
custom_daily_file_name_calculator>;
using sink_type = spdlog::sinks::daily_file_sink<std::mutex, custom_daily_file_name_calculator>;
prepare_logdir();
//calculate filename (time based)
// calculate filename (time based)
std::string basename = "logs/daily_dateonly";
std::tm tm = spdlog::details::os::localtime();
fmt::MemoryWriter w;
@ -188,7 +179,6 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger_custom]]")
REQUIRE(count_lines(filename) == 10);
}
/*
* File name calculations
*/
@ -211,12 +201,8 @@ TEST_CASE("rotating_file_sink::calc_filename3", "[rotating_file_sink]]")
REQUIRE(filename == "rotated.txt");
}
// regex supported only from gcc 4.9 and above
#if defined (_MSC_VER) || !(__GNUC__ <= 4 && __GNUC_MINOR__ < 9)
#if defined(_MSC_VER) || !(__GNUC__ <= 4 && __GNUC_MINOR__ < 9)
#include <regex>
TEST_CASE("daily_file_sink::default_daily_file_name_calculator1", "[daily_file_sink]]")
{

View File

@ -1,18 +1,17 @@
#pragma once
#include <cstdio>
#include <fstream>
#include <string>
#include <ostream>
#include <chrono>
#include <exception>
#include "catch.hpp"
#include "utils.h"
#include <chrono>
#include <cstdio>
#include <exception>
#include <fstream>
#include <ostream>
#include <string>
#define SPDLOG_TRACE_ON
#define SPDLOG_DEBUG_ON
#include "../include/spdlog/spdlog.h"
#include "../include/spdlog/sinks/null_sink.h"
#include "../include/spdlog/sinks/ostream_sink.h"
#include "../include/spdlog/spdlog.h"

View File

@ -7,23 +7,24 @@ TEST_CASE("register_drop", "[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name);
REQUIRE(spdlog::get(tested_logger_name)!=nullptr);
//Throw if registring existing name
REQUIRE(spdlog::get(tested_logger_name) != nullptr);
// Throw if registring existing name
REQUIRE_THROWS_AS(spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name), spdlog::spdlog_ex);
}
TEST_CASE("explicit register" "[registry]")
TEST_CASE("explicit register"
"[registry]")
{
spdlog::drop_all();
auto logger = std::make_shared<spdlog::logger>(tested_logger_name, std::make_shared<spdlog::sinks::null_sink_st>());
spdlog::register_logger(logger);
REQUIRE(spdlog::get(tested_logger_name) != nullptr);
//Throw if registring existing name
// Throw if registring existing name
REQUIRE_THROWS_AS(spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name), spdlog::spdlog_ex);
}
TEST_CASE("apply_all" "[registry]")
TEST_CASE("apply_all"
"[registry]")
{
spdlog::drop_all();
auto logger = std::make_shared<spdlog::logger>(tested_logger_name, std::make_shared<spdlog::sinks::null_sink_st>());
@ -32,26 +33,20 @@ TEST_CASE("apply_all" "[registry]")
spdlog::register_logger(logger2);
int counter = 0;
spdlog::apply_all([&counter](std::shared_ptr<spdlog::logger> l)
{
counter++;
});
spdlog::apply_all([&counter](std::shared_ptr<spdlog::logger> l) { counter++; });
REQUIRE(counter == 2);
counter = 0;
spdlog::drop(tested_logger_name2);
spdlog::apply_all([&counter](std::shared_ptr<spdlog::logger> l)
{
spdlog::apply_all([&counter](std::shared_ptr<spdlog::logger> l) {
REQUIRE(l->name() == tested_logger_name);
counter++;
}
);
});
REQUIRE(counter == 1);
}
TEST_CASE("drop" "[registry]")
TEST_CASE("drop"
"[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name);
@ -59,7 +54,8 @@ TEST_CASE("drop" "[registry]")
REQUIRE_FALSE(spdlog::get(tested_logger_name));
}
TEST_CASE("drop_all" "[registry]")
TEST_CASE("drop_all"
"[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name);
@ -69,8 +65,8 @@ TEST_CASE("drop_all" "[registry]")
REQUIRE_FALSE(spdlog::get(tested_logger_name));
}
TEST_CASE("drop non existing" "[registry]")
TEST_CASE("drop non existing"
"[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name);
@ -79,6 +75,3 @@ TEST_CASE("drop non existing" "[registry]")
REQUIRE(spdlog::get(tested_logger_name));
spdlog::drop_all();
}

View File

@ -1,6 +1,6 @@
/*
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
#include "includes.h"
@ -14,7 +14,7 @@ TEST_CASE("debug and trace w/o format string", "[macros]]")
logger->set_level(spdlog::level::trace);
SPDLOG_TRACE(logger, "Test message 1");
//SPDLOG_DEBUG(logger, "Test message 2");
// SPDLOG_DEBUG(logger, "Test message 2");
SPDLOG_DEBUG(logger, "Test message 2");
logger->flush();
@ -22,7 +22,6 @@ TEST_CASE("debug and trace w/o format string", "[macros]]")
REQUIRE(count_lines(filename) == 2);
}
TEST_CASE("debug and trace with format strings", "[macros]]")
{
prepare_logdir();
@ -34,11 +33,11 @@ TEST_CASE("debug and trace with format strings", "[macros]]")
#if !defined(SPDLOG_FMT_PRINTF)
SPDLOG_TRACE(logger, "Test message {}", 1);
//SPDLOG_DEBUG(logger, "Test message 2");
// SPDLOG_DEBUG(logger, "Test message 2");
SPDLOG_DEBUG(logger, "Test message {}", 222);
#else
SPDLOG_TRACE(logger, "Test message %d", 1);
//SPDLOG_DEBUG(logger, "Test message 2");
// SPDLOG_DEBUG(logger, "Test message 2");
SPDLOG_DEBUG(logger, "Test message %d", 222);
#endif
@ -47,4 +46,3 @@ TEST_CASE("debug and trace with format strings", "[macros]]")
REQUIRE(ends_with(file_contents(filename), "Test message 222\n"));
REQUIRE(count_lines(filename) == 2);
}

View File

@ -1,13 +1,14 @@
#include "includes.h"
// log to str and return it
static std::string log_to_str(const std::string& msg, const std::shared_ptr<spdlog::formatter>& formatter = nullptr)
static std::string log_to_str(const std::string &msg, const std::shared_ptr<spdlog::formatter> &formatter = nullptr)
{
std::ostringstream oss;
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
spdlog::logger oss_logger("pattern_tester", oss_sink);
oss_logger.set_level(spdlog::level::info);
if (formatter) oss_logger.set_formatter(formatter);
if (formatter)
oss_logger.set_formatter(formatter);
oss_logger.info(msg);
return oss.str();
}
@ -56,6 +57,7 @@ TEST_CASE("date MM/DD/YY ", "[pattern_formatter]")
auto formatter = std::make_shared<spdlog::pattern_formatter>("%D %v", spdlog::pattern_time_type::local, "\n");
auto now_tm = spdlog::details::os::localtime();
std::stringstream oss;
oss << std::setfill('0') << std::setw(2) << now_tm.tm_mon + 1 << "/" << std::setw(2) << now_tm.tm_mday << "/" << std::setw(2) << (now_tm.tm_year + 1900) % 1000 << " Some message\n";
oss << std::setfill('0') << std::setw(2) << now_tm.tm_mon + 1 << "/" << std::setw(2) << now_tm.tm_mday << "/" << std::setw(2)
<< (now_tm.tm_year + 1900) % 1000 << " Some message\n";
REQUIRE(log_to_str("Some message", formatter) == oss.str());
}

View File

@ -1,6 +1,5 @@
#include "includes.h"
void prepare_logdir()
{
spdlog::drop_all();
@ -14,18 +13,15 @@ void prepare_logdir()
#endif
}
std::string file_contents(const std::string& filename)
std::string file_contents(const std::string &filename)
{
std::ifstream ifs(filename);
if (!ifs)
throw std::runtime_error("Failed open file ");
return std::string((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>()));
return std::string((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
}
std::size_t count_lines(const std::string& filename)
std::size_t count_lines(const std::string &filename)
{
std::ifstream ifs(filename);
if (!ifs)
@ -33,12 +29,12 @@ std::size_t count_lines(const std::string& filename)
std::string line;
size_t counter = 0;
while(std::getline(ifs, line))
while (std::getline(ifs, line))
counter++;
return counter;
}
std::size_t get_filesize(const std::string& filename)
std::size_t get_filesize(const std::string &filename)
{
std::ifstream ifs(filename, std::ifstream::ate | std::ifstream::binary);
if (!ifs)
@ -47,10 +43,10 @@ std::size_t get_filesize(const std::string& filename)
return static_cast<std::size_t>(ifs.tellg());
}
// source: https://stackoverflow.com/a/2072890/192001
bool ends_with(std::string const & value, std::string const & ending)
bool ends_with(std::string const &value, std::string const &ending)
{
if (ending.size() > value.size()) return false;
if (ending.size() > value.size())
return false;
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}

View File

@ -1,16 +1,16 @@
#pragma once
#include <cstddef>
#include <string>
#include<cstddef>
std::size_t count_lines(const std::string& filename);
std::size_t count_lines(const std::string &filename);
void prepare_logdir();
std::string file_contents(const std::string& filename);
std::string file_contents(const std::string &filename);
std::size_t count_lines(const std::string& filename);
std::size_t count_lines(const std::string &filename);
std::size_t get_filesize(const std::string& filename);
std::size_t get_filesize(const std::string &filename);
bool ends_with(std::string const & value, std::string const & ending);
bool ends_with(std::string const &value, std::string const &ending);