Commit f9019870 authored by gabime's avatar gabime

Merge branch 'v1.x' of https://github.com/gabime/spdlog into v1.x

parents 00546824 60ca07c2
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# #
cmake_minimum_required(VERSION 3.1) cmake_minimum_required(VERSION 3.1)
project(spdlog VERSION 0.16.3 LANGUAGES CXX) project(spdlog VERSION 1.0.0 LANGUAGES CXX)
include(CTest) include(CTest)
include(CMakeDependentOption) include(CMakeDependentOption)
include(GNUInstallDirs) include(GNUInstallDirs)
......
This diff is collapsed.
CXX ?= g++ CXX = g++
CXXFLAGS = -march=native -Wall -Wextra -pedantic -std=c++11 -pthread -I../include CXXFLAGS = -march=native -Wall -Wextra -pedantic -std=c++11 -pthread -I../include -fmax-errors=1
CXX_RELEASE_FLAGS = -O3 -flto -DNDEBUG CXX_RELEASE_FLAGS = -O3 -flto
binaries=bench spdlog-null-async binaries=bench latency
all: $(binaries) all: $(binaries)
bench: bench.cpp bench: bench.cpp
$(CXX) bench.cpp -o bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS) $(CXX) bench.cpp -o bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
spdlog-null-async: spdlog-null-async.cpp
$(CXX) spdlog-null-async.cpp -o spdlog-null-async $(CXXFLAGS) $(CXX_RELEASE_FLAGS) latency: latency.cpp
$(CXX) latency.cpp -o latency $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
.PHONY: clean .PHONY: clean
......
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
// bench.cpp : spdlog benchmarks // bench.cpp : spdlog benchmarks
// //
#include "spdlog/async.h" #include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h" #include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h" #include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/simple_file_sink.h"
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include "utils.h" #include "utils.h"
#include <atomic> #include <atomic>
...@@ -32,8 +32,9 @@ void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count ...@@ -32,8 +32,9 @@ 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;
int howmany = 1000000; int howmany = 1000000;
int queue_size = howmany + 2;
int threads = 10; int threads = 10;
int file_size = 30 * 1024 * 1024; int file_size = 30 * 1024 * 1024;
int rotating_files = 5; int rotating_files = 5;
...@@ -52,16 +53,24 @@ int main(int argc, char *argv[]) ...@@ -52,16 +53,24 @@ int main(int argc, char *argv[])
cout << "Single thread, " << format(howmany) << " iterations" << endl; cout << "Single thread, " << format(howmany) << " iterations" << endl;
cout << "*******************************************************************************\n"; cout << "*******************************************************************************\n";
auto basic_st = spdlog::basic_logger_mt("basic_st", "logs/basic_st.log", true);
bench(howmany, basic_st);
auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files); auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files);
bench(howmany, rotating_st); bench(howmany, rotating_st);
auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log"); auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log");
bench(howmany, daily_st); bench(howmany, daily_st);
bench(howmany, spdlog::create<null_sink_st>("null_st")); bench(howmany, spdlog::create<null_sink_st>("null_st"));
cout << "\n*******************************************************************************\n"; cout << "\n*******************************************************************************\n";
cout << threads << " threads sharing same logger, " << format(howmany) << " iterations" << endl; cout << threads << " threads sharing same logger, " << format(howmany) << " iterations" << endl;
cout << "*******************************************************************************\n"; cout << "*******************************************************************************\n";
auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs/basic_mt.log", true);
bench_mt(howmany, basic_mt, threads);
auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files); auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files);
bench_mt(howmany, rotating_mt, threads); bench_mt(howmany, rotating_mt, threads);
...@@ -76,9 +85,9 @@ int main(int argc, char *argv[]) ...@@ -76,9 +85,9 @@ int main(int argc, char *argv[])
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ {
spdlog::init_thread_pool(queue_size, 1); spdlog::init_thread_pool(queue_size, 1);
auto as = spdlog::basic_logger_mt<spdlog::create_async>("as", "logs/basic_async.log", true); auto as = spdlog::basic_logger_mt<spdlog::async_factory>("async", "logs/basic_async.log", true);
bench_mt(howmany, as, threads); bench_mt(howmany, as, threads);
spdlog::drop("as"); spdlog::drop("async");
} }
} }
catch (std::exception &ex) catch (std::exception &ex)
...@@ -92,34 +101,31 @@ int main(int argc, char *argv[]) ...@@ -92,34 +101,31 @@ int main(int argc, char *argv[])
void bench(int howmany, std::shared_ptr<spdlog::logger> log) void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{ {
using std::chrono::high_resolution_clock;
cout << log->name() << "...\t\t" << flush; cout << log->name() << "...\t\t" << flush;
auto start = system_clock::now(); auto start = high_resolution_clock::now();
for (auto i = 0; i < howmany; ++i) for (auto i = 0; i < howmany; ++i)
{ {
log->info("Hello logger: msg number {}", i); log->info("Hello logger: msg number {}", i);
} }
auto delta = system_clock::now() - start; auto delta = high_resolution_clock::now() - start;
auto delta_d = duration_cast<duration<double>>(delta).count(); auto delta_d = duration_cast<duration<double>>(delta).count();
cout << "Elapsed: " << delta_d << "\t" << format(int(howmany / delta_d)) << "/sec" << endl; cout << "Elapsed: " << delta_d << "\t" << format(int(howmany / delta_d)) << "/sec" << endl;
} }
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count) void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{ {
using std::chrono::high_resolution_clock;
cout << log->name() << "...\t\t" << flush; cout << log->name() << "...\t\t" << flush;
std::atomic<int> msg_counter{0};
vector<thread> threads; vector<thread> threads;
auto start = system_clock::now(); auto start = high_resolution_clock::now();
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() { threads.push_back(std::thread([&]() {
for (;;) for (int j = 0; j < howmany / thread_count; j++)
{ {
int counter = ++msg_counter; log->info("Hello logger: msg number {}", j);
if (counter > howmany)
break;
log->info("Hello logger: msg number {}", counter);
} }
})); }));
} }
...@@ -129,7 +135,7 @@ void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count ...@@ -129,7 +135,7 @@ void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count
t.join(); t.join();
}; };
auto delta = system_clock::now() - start; auto delta = high_resolution_clock::now() - start;
auto delta_d = duration_cast<duration<double>>(delta).count(); auto delta_d = duration_cast<duration<double>>(delta).count();
cout << "Elapsed: " << delta_d << "\t" << format(int(howmany / delta_d)) << "/sec" << endl; cout << "Elapsed: " << delta_d << "\t" << format(int(howmany / delta_d)) << "/sec" << endl;
} }
//
// Copyright(c) 2018 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
//
// latency.cpp : spdlog latency benchmarks
//
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/spdlog.h"
#include "utils.h"
#include <atomic>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
using namespace std;
using namespace std::chrono;
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 , char *[])
{
std::srand(std::time(nullptr)); // use current time as seed for random generator
int howmany = 1000000;
int queue_size = howmany + 2;
int threads = 10;
int file_size = 30 * 1024 * 1024;
int rotating_files = 5;
try
{
cout << "*******************************************************************************\n";
cout << "Single thread\n";
cout << "*******************************************************************************\n";
auto basic_st = spdlog::basic_logger_mt("basic_st", "logs/basic_st.log", true);
bench(howmany, basic_st);
auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files);
bench(howmany, rotating_st);
auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log");
bench(howmany, daily_st);
bench(howmany, spdlog::create<null_sink_st>("null_st"));
cout << "\n*******************************************************************************\n";
cout << threads << " threads sharing same logger\n";
cout << "*******************************************************************************\n";
auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs/basic_mt.log", true);
bench_mt(howmany, basic_mt, threads);
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"));
cout << "\n*******************************************************************************\n";
cout << "async logging.. " << threads << " threads sharing same logger\n";
cout << "*******************************************************************************\n";
for (int i = 0; i < 3; ++i)
{
spdlog::init_thread_pool(queue_size, 1);
auto as = spdlog::basic_logger_mt<spdlog::async_factory>("async", "logs/basic_async.log", true);
bench_mt(howmany, as, threads);
spdlog::drop("async");
}
}
catch (std::exception &ex)
{
std::cerr << "Error: " << ex.what() << std::endl;
perror("Last error");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{
using namespace std::chrono;
using chrono::high_resolution_clock;
using chrono::milliseconds;
using chrono::nanoseconds;
cout << log->name() << "...\t\t" << flush;
nanoseconds total_nanos = nanoseconds::zero();
for (auto i = 0; i < howmany; ++i)
{
auto start = high_resolution_clock::now();
log->info("Hello logger: msg number {}", i);
auto delta_nanos = chrono::duration_cast<nanoseconds>(high_resolution_clock::now() - start);
total_nanos+= delta_nanos;
}
auto avg = total_nanos.count()/howmany;
cout << format(avg) << " ns/call" << endl;
}
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{
using namespace std::chrono;
using chrono::high_resolution_clock;
using chrono::milliseconds;
using chrono::nanoseconds;
cout << log->name() << "...\t\t" << flush;
vector<thread> threads;
std::atomic<nanoseconds::rep> total_nanos{0};
for (int t = 0; t < thread_count; ++t)
{
threads.push_back(std::thread([&]() {
for (int j = 0; j < howmany / thread_count; j++)
{
auto start = high_resolution_clock::now();
log->info("Hello logger: msg number {}", j);
auto delta_nanos = chrono::duration_cast<nanoseconds>(high_resolution_clock::now() - start);
total_nanos+= delta_nanos.count();
}
}));
}
for (auto &t : threads)
{
t.join();
};
auto avg = total_nanos/howmany;
cout << format(avg) << " ns/call" << endl;
}
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <vector> #include <vector>
#include "spdlog/async.h" #include "spdlog/async.h"
#include "spdlog/sinks/simple_file_sink.h" #include "spdlog/sinks/basic_file_sink.h"
using namespace std; using namespace std;
...@@ -27,7 +27,7 @@ int main(int argc, char *argv[]) ...@@ -27,7 +27,7 @@ int main(int argc, char *argv[])
int howmany = 1000000; int howmany = 1000000;
spdlog::init_thread_pool(howmany, 1); spdlog::init_thread_pool(howmany, 1);
auto logger = spdlog::create_async_logger<spdlog::sinks::simple_file_sink_mt>("file_logger", "logs/spdlog-bench-async.log", false); auto logger = spdlog::create_async_logger<spdlog::sinks::basic_file_sink_mt>("file_logger", "logs/spdlog-bench-async.log", false);
logger->set_pattern("[%Y-%m-%d %T.%F]: %L %t %v"); logger->set_pattern("[%Y-%m-%d %T.%F]: %L %t %v");
std::cout << "To stop, press <Enter>" << std::endl; std::cout << "To stop, press <Enter>" << std::endl;
......
//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
//
// bench.cpp : spdlog benchmarks
//
#include "spdlog/async.h"
#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>
using namespace std;
using namespace std::chrono;
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 howmany;
int tp_queue_size;
int tp_threads = 1;
int client_threads = 10;
int iters = 10;
try
{
if (argc < 2)
{
cout << "Usage: " << argv[0] << " <howmany> [client_threads] [q_size] [tp_threads]" << endl;
return (1);
}
howmany = atoi(argv[1]);
if (argc > 2)
client_threads = atoi(argv[2]);
if (argc > 3)
tp_queue_size = atoi(argv[3]);
else
tp_queue_size = howmany;
if (argc > 4)
tp_threads = atoi(argv[4]);
cout << "\n*******************************************************************************\n";
cout << "messages:\t" << format(howmany) << endl;
cout << "client_threads:\t" << client_threads << endl;
cout << "tp queue:\t" << format(tp_queue_size) << endl;
cout << "tp threads:\t" << tp_threads << endl;
cout << "*******************************************************************************\n";
size_t total_rate = 0;
for (int i = 0; i < iters; ++i)
{
spdlog::init_thread_pool(tp_queue_size, tp_threads);
auto as = spdlog::create_async_logger<null_sink_mt>("async(null-sink)");
total_rate += bench_as(howmany, as, client_threads);
spdlog::drop("async(null-sink)");
}
std::cout << endl;
std::cout << "Avg rate: " << format(total_rate / iters) << "/sec" << std::endl;
}
catch (std::exception &ex)
{
std::cerr << "Error: " << ex.what() << std::endl;
perror("Last error");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
// 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};
vector<thread> threads;
auto start = system_clock::now();
for (int t = 0; t < thread_count; ++t)
{
threads.push_back(std::thread([&]() {
for (;;)
{
int counter = ++msg_counter;
if (counter > howmany)
break;
log->info("Hello logger: msg number {}", counter);
}
}));
}
for (auto &t : threads)
{
t.join();
}
auto delta = system_clock::now() - start;
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;
}
CXX = g++ CXX = g++
CXX_FLAGS = -Wall -Wextra -pedantic -std=c++11 -pthread -I../include CXX_FLAGS = -Wall -Wextra -pedantic -std=c++11 -pthread -I../include -fmax-errors=1
CXX_RELEASE_FLAGS = -O3 -march=native CXX_RELEASE_FLAGS = -O3 -march=native
CXX_DEBUG_FLAGS= -g CXX_DEBUG_FLAGS= -g
......
This diff is collapsed.
...@@ -15,8 +15,8 @@ int main(int, char *[]) ...@@ -15,8 +15,8 @@ int main(int, char *[])
// Each sink can have it's own log level and a message will be logged. // Each sink can have it's own log level and a message will be logged.
std::vector<spdlog::sink_ptr> sinks; 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::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::basic_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::basic_file_sink_mt>("./log_debug_file.txt"));
spdlog::logger console_multisink("multisink", sinks.begin(), sinks.end()); spdlog::logger console_multisink("multisink", sinks.begin(), sinks.end());
console_multisink.set_level(spdlog::level::warn); console_multisink.set_level(spdlog::level::warn);
......
...@@ -23,7 +23,7 @@ namespace spdlog { ...@@ -23,7 +23,7 @@ namespace spdlog {
// async logger factory - creates async loggers backed with thread pool. // async logger factory - creates async loggers backed with thread pool.
// if a global thread pool doesn't already exist, create it with default queue size of 8192 items and single thread. // if a global thread pool doesn't already exist, create it with default queue size of 8192 items and single thread.
struct create_async struct async_factory
{ {
template<typename Sink, typename... SinkArgs> template<typename Sink, typename... SinkArgs>
static std::shared_ptr<async_logger> create(const std::string &logger_name, SinkArgs &&... args) static std::shared_ptr<async_logger> create(const std::string &logger_name, SinkArgs &&... args)
...@@ -39,16 +39,16 @@ struct create_async ...@@ -39,16 +39,16 @@ struct create_async
} }
auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...); auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);
auto new_logger = std::make_shared<async_logger>(logger_name, std::move(sink), std::move(tp), async_overflow_policy::block_retry); auto new_logger = std::make_shared<async_logger>(logger_name, std::move(sink), std::move(tp), async_overflow_policy::block);
registry::instance().register_and_init(new_logger); registry::instance().register_and_init(new_logger);
return new_logger; return new_logger;
} }
}; };
template<typename Sink, typename... SinkArgs> template<typename Sink, typename... SinkArgs>
inline std::shared_ptr<spdlog::logger> create_async_logger(const std::string &logger_name, SinkArgs &&... sink_args) inline std::shared_ptr<spdlog::logger> create_async(const std::string &logger_name, SinkArgs &&... sink_args)
{ {
return create_async::create<Sink>(logger_name, std::forward<SinkArgs>(sink_args)...); return async_factory::create<Sink>(logger_name, std::forward<SinkArgs>(sink_args)...);
} }
// set global thread pool. // set global thread pool.
......
...@@ -34,13 +34,13 @@ class async_logger SPDLOG_FINAL : public std::enable_shared_from_this<async_logg ...@@ -34,13 +34,13 @@ class async_logger SPDLOG_FINAL : public std::enable_shared_from_this<async_logg
public: public:
template<class It> template<class It>
async_logger(const std::string &logger_name, const It &begin, const It &end, std::weak_ptr<details::thread_pool> tp, async_logger(const std::string &logger_name, const It &begin, const It &end, std::weak_ptr<details::thread_pool> tp,
async_overflow_policy overflow_policy = async_overflow_policy::block_retry); async_overflow_policy overflow_policy = async_overflow_policy::block);
async_logger(const std::string &logger_name, sinks_init_list sinks, std::weak_ptr<details::thread_pool> tp, async_logger(const std::string &logger_name, sinks_init_list sinks, std::weak_ptr<details::thread_pool> tp,
async_overflow_policy overflow_policy = async_overflow_policy::block_retry); async_overflow_policy overflow_policy = async_overflow_policy::block);
async_logger(const std::string &logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp, async_logger(const std::string &logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp,
async_overflow_policy overflow_policy = async_overflow_policy::block_retry); async_overflow_policy overflow_policy = async_overflow_policy::block);
protected: protected:
void sink_it_(details::log_msg &msg) override; void sink_it_(details::log_msg &msg) override;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#pragma once #pragma once
#define SPDLOG_VERSION "0.16.4-rc" #define SPDLOG_VERSION "1.0.0-rc"
#include "spdlog/tweakme.h" #include "spdlog/tweakme.h"
...@@ -63,6 +63,7 @@ using log_clock = std::chrono::system_clock; ...@@ -63,6 +63,7 @@ using log_clock = std::chrono::system_clock;
using sink_ptr = std::shared_ptr<sinks::sink>; using sink_ptr = std::shared_ptr<sinks::sink>;
using sinks_init_list = std::initializer_list<sink_ptr>; using sinks_init_list = std::initializer_list<sink_ptr>;
using formatter_ptr = std::shared_ptr<spdlog::formatter>; using formatter_ptr = std::shared_ptr<spdlog::formatter>;
#if defined(SPDLOG_NO_ATOMIC_LEVELS) #if defined(SPDLOG_NO_ATOMIC_LEVELS)
using level_t = details::null_atomic_int; using level_t = details::null_atomic_int;
#else #else
...@@ -126,8 +127,8 @@ using level_hasher = std::hash<int>; ...@@ -126,8 +127,8 @@ using level_hasher = std::hash<int>;
// //
enum class async_overflow_policy enum class async_overflow_policy
{ {
block_retry, // Block until message can be enqueued block, // Block until message can be enqueued
overrun_oldeset // Discard oldest message in the queue if full when trying to add new item. overrun_oldest // Discard oldest message in the queue if full when trying to add new item.
}; };
// //
......
...@@ -60,7 +60,7 @@ inline void spdlog::async_logger::flush_() ...@@ -60,7 +60,7 @@ inline void spdlog::async_logger::flush_()
} }
else else
{ {
throw spdlog_ex("async flush: thread pool doens't exist anymore"); throw spdlog_ex("async flush: thread pool doesn't exist anymore");
} }
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "stdio.h" #include "stdio.h"
namespace spdlog { namespace spdlog {
namespace details { namespace details {
struct console_stdout_trait struct console_stdout_stream
{ {
static FILE *stream() static FILE *stream()
{ {
...@@ -21,7 +21,7 @@ struct console_stdout_trait ...@@ -21,7 +21,7 @@ struct console_stdout_trait
#endif #endif
}; };
struct console_stderr_trait struct console_stderr_stream
{ {
static FILE *stream() static FILE *stream()
{ {
...@@ -35,7 +35,7 @@ struct console_stderr_trait ...@@ -35,7 +35,7 @@ struct console_stderr_trait
#endif #endif
}; };
struct console_mutex_trait struct console_global_mutex
{ {
using mutex_t = std::mutex; using mutex_t = std::mutex;
static mutex_t &console_mutex() static mutex_t &console_mutex()
...@@ -45,7 +45,7 @@ struct console_mutex_trait ...@@ -45,7 +45,7 @@ struct console_mutex_trait
} }
}; };
struct console_null_mutex_trait struct console_global_nullmutex
{ {
using mutex_t = null_mutex; using mutex_t = null_mutex;
static mutex_t &console_mutex() static mutex_t &console_mutex()
......
...@@ -8,13 +8,16 @@ ...@@ -8,13 +8,16 @@
namespace spdlog { namespace spdlog {
namespace details { namespace details {
namespace fmt_helper { namespace fmt_helper {
inline void append_str(const std::string &str, fmt::memory_buffer &dest)
template <size_t Buffer_Size>
inline void append_str(const std::string &str, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
{ {
auto *str_ptr = str.data(); auto *str_ptr = str.data();
dest.append(str_ptr, str_ptr + str.size()); dest.append(str_ptr, str_ptr + str.size());
} }
inline void append_c_str(const char *c_str, fmt::memory_buffer &dest) template <size_t Buffer_Size>
inline void append_c_str(const char *c_str, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
{ {
char ch; char ch;
while ((ch = *c_str) != '\0') while ((ch = *c_str) != '\0')
...@@ -24,21 +27,22 @@ inline void append_c_str(const char *c_str, fmt::memory_buffer &dest) ...@@ -24,21 +27,22 @@ inline void append_c_str(const char *c_str, fmt::memory_buffer &dest)
} }
} }
template<size_t N1, size_t N2> template<size_t Buffer_Size1, size_t Buffer_Size2>
inline void append_buf(const fmt::basic_memory_buffer<char, N1> &buf, fmt::basic_memory_buffer<char, N2> &dest) inline void append_buf(const fmt::basic_memory_buffer<char, Buffer_Size1> &buf, fmt::basic_memory_buffer<char, Buffer_Size2> &dest)
{ {
auto *buf_ptr = buf.data(); auto *buf_ptr = buf.data();
dest.append(buf_ptr, buf_ptr + buf.size()); dest.append(buf_ptr, buf_ptr + buf.size());
} }
template<typename T> template<typename T, size_t Buffer_Size>
inline void append_int(T n, fmt::memory_buffer &dest) inline void append_int(T n, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
{ {
fmt::format_int i(n); fmt::format_int i(n);
dest.append(i.data(), i.data() + i.size()); dest.append(i.data(), i.data() + i.size());
} }
inline void pad2(int n, fmt::memory_buffer &dest) template <size_t Buffer_Size>
inline void pad2(int n, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
{ {
if (n > 99) if (n > 99)
{ {
...@@ -61,7 +65,8 @@ inline void pad2(int n, fmt::memory_buffer &dest) ...@@ -61,7 +65,8 @@ inline void pad2(int n, fmt::memory_buffer &dest)
fmt::format_to(dest, "{:02}", n); fmt::format_to(dest, "{:02}", n);
} }
inline void pad3(int n, fmt::memory_buffer &dest) template <size_t Buffer_Size>
inline void pad3(int n, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
{ {
if (n > 99) if (n > 99)
{ {
...@@ -86,8 +91,13 @@ inline void pad3(int n, fmt::memory_buffer &dest) ...@@ -86,8 +91,13 @@ inline void pad3(int n, fmt::memory_buffer &dest)
fmt::format_to(dest, "{:03}", n); fmt::format_to(dest, "{:03}", n);
} }
inline void pad6(size_t n, fmt::memory_buffer &dest) template <size_t Buffer_Size>
inline void pad6(size_t n, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
{ {
// todo: maybe replace this implementation with
// pad3(n / 1000, dest);
// pad3(n % 1000, dest);
if (n > 99999) if (n > 99999)
{ {
append_int(n, dest); append_int(n, dest);
...@@ -122,7 +132,7 @@ inline void pad6(size_t n, fmt::memory_buffer &dest) ...@@ -122,7 +132,7 @@ inline void pad6(size_t n, fmt::memory_buffer &dest)
dest.push_back('0'); dest.push_back('0');
dest.push_back('0'); dest.push_back('0');
dest.push_back('0'); dest.push_back('0');
} }
append_int(n, dest); append_int(n, dest);
} }
......
...@@ -46,9 +46,9 @@ inline void spdlog::logger::set_formatter(const Args &... args) ...@@ -46,9 +46,9 @@ inline void spdlog::logger::set_formatter(const Args &... args)
} }
} }
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 time_type)
{ {
set_formatter<spdlog::pattern_formatter>(pattern, pattern_time); set_formatter<spdlog::pattern_formatter>(pattern, time_type);
} }
template<typename... Args> template<typename... Args>
...@@ -100,40 +100,40 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg) ...@@ -100,40 +100,40 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
SPDLOG_CATCH_AND_HANDLE SPDLOG_CATCH_AND_HANDLE
} }
template<typename Arg1, typename... Args> template<typename... Args>
inline void spdlog::logger::trace(const char *fmt, const Arg1 &arg1, const Args &... args) inline void spdlog::logger::trace(const char *fmt, const Args &... args)
{ {
log(level::trace, fmt, arg1, args...); log(level::trace, fmt, args...);
} }
template<typename Arg1, typename... Args> template<typename... Args>
inline void spdlog::logger::debug(const char *fmt, const Arg1 &arg1, const Args &... args) inline void spdlog::logger::debug(const char *fmt, const Args &... args)
{ {
log(level::debug, fmt, arg1, args...); log(level::debug, fmt, args...);
} }
template<typename Arg1, typename... Args> template<typename... Args>
inline void spdlog::logger::info(const char *fmt, const Arg1 &arg1, const Args &... args) inline void spdlog::logger::info(const char *fmt, const Args &... args)
{ {
log(level::info, fmt, arg1, args...); log(level::info, fmt, args...);
} }
template<typename Arg1, typename... Args> template<typename... Args>
inline void spdlog::logger::warn(const char *fmt, const Arg1 &arg1, const Args &... args) inline void spdlog::logger::warn(const char *fmt, const Args &... args)
{ {
log(level::warn, fmt, arg1, args...); log(level::warn, fmt, args...);
} }
template<typename Arg1, typename... Args> template<typename... Args>
inline void spdlog::logger::error(const char *fmt, const Arg1 &arg1, const Args &... args) inline void spdlog::logger::error(const char *fmt, const Args &... args)
{ {
log(level::err, fmt, arg1, args...); log(level::err, fmt, args...);
} }
template<typename Arg1, typename... Args> template<typename... Args>
inline void spdlog::logger::critical(const char *fmt, const Arg1 &arg1, const Args &... args) inline void spdlog::logger::critical(const char *fmt, const Args &... args)
{ {
log(level::critical, fmt, arg1, args...); log(level::critical, fmt, args...);
} }
template<typename T> template<typename T>
......
...@@ -120,7 +120,16 @@ class c_formatter SPDLOG_FINAL : public flag_formatter ...@@ -120,7 +120,16 @@ class c_formatter SPDLOG_FINAL : public flag_formatter
{ {
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{ {
fmt::format_to(dest, "{} {} {} ", days[tm_time.tm_wday], months[tm_time.tm_mon], tm_time.tm_mday); // //fmt::format_to(dest, "{} {} {} ", days[tm_time.tm_wday], months[tm_time.tm_mon], tm_time.tm_mday);
// date
fmt_helper::append_str(days[tm_time.tm_wday], dest);
dest.push_back(' ');
fmt_helper::append_str(months[tm_time.tm_mon], dest);
dest.push_back(' ');
fmt_helper::append_int(tm_time.tm_mday, dest);
dest.push_back(' ');
// time
fmt_helper::pad2(tm_time.tm_hour, dest); fmt_helper::pad2(tm_time.tm_hour, dest);
dest.push_back(':'); dest.push_back(':');
fmt_helper::pad2(tm_time.tm_min, dest); fmt_helper::pad2(tm_time.tm_min, dest);
...@@ -176,7 +185,6 @@ class d_formatter SPDLOG_FINAL : public flag_formatter ...@@ -176,7 +185,6 @@ class d_formatter SPDLOG_FINAL : public flag_formatter
{ {
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{ {
// fmt::format_to(dest, "{:02}", tm_time.tm_mday);
fmt_helper::pad2(tm_time.tm_mday, dest); fmt_helper::pad2(tm_time.tm_mday, dest);
} }
}; };
...@@ -265,7 +273,7 @@ class p_formatter SPDLOG_FINAL : public flag_formatter ...@@ -265,7 +273,7 @@ class p_formatter SPDLOG_FINAL : public flag_formatter
{ {
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{ {
fmt::format_to(dest, "{}", ampm(tm_time)); fmt_helper::append_c_str(ampm(tm_time), dest);
} }
}; };
...@@ -274,13 +282,13 @@ class r_formatter SPDLOG_FINAL : public flag_formatter ...@@ -274,13 +282,13 @@ class r_formatter SPDLOG_FINAL : public flag_formatter
{ {
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{ {
// fmt::format_to(dest, "{:02}:{:02}:{:02} {}", to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ampm(tm_time));
fmt_helper::pad2(to12h(tm_time), dest); fmt_helper::pad2(to12h(tm_time), dest);
dest.push_back(':'); dest.push_back(':');
fmt_helper::pad2(tm_time.tm_min, dest); fmt_helper::pad2(tm_time.tm_min, dest);
dest.push_back(':'); dest.push_back(':');
fmt_helper::pad2(tm_time.tm_sec, dest); fmt_helper::pad2(tm_time.tm_sec, dest);
fmt::format_to(dest, " {}", ampm(tm_time)); dest.push_back(' ');
fmt_helper::append_c_str(ampm(tm_time), dest);
} }
}; };
...@@ -330,23 +338,19 @@ public: ...@@ -330,23 +338,19 @@ public:
int total_minutes = os::utc_minutes_offset(tm_time); int total_minutes = os::utc_minutes_offset(tm_time);
#endif #endif
bool is_negative = total_minutes < 0; bool is_negative = total_minutes < 0;
char sign;
if (is_negative) if (is_negative)
{ {
total_minutes = -total_minutes; total_minutes = -total_minutes;
sign = '-'; dest.push_back('-');
} }
else else
{ {
sign = '+'; dest.push_back('+');
} }
int h = total_minutes / 60; fmt_helper::pad2(total_minutes / 60, dest); // hours
int m = total_minutes % 60;
dest.push_back(sign);
fmt_helper::pad2(h, dest);
dest.push_back(':'); dest.push_back(':');
fmt_helper::pad2(m, dest); fmt_helper::pad2(total_minutes % 60, dest); // minutes
} }
private: private:
...@@ -371,7 +375,6 @@ class t_formatter SPDLOG_FINAL : public flag_formatter ...@@ -371,7 +375,6 @@ class t_formatter SPDLOG_FINAL : public flag_formatter
{ {
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{ {
fmt_helper::pad6(msg.thread_id, dest); fmt_helper::pad6(msg.thread_id, dest);
} }
}; };
...@@ -390,7 +393,6 @@ class i_formatter SPDLOG_FINAL : public flag_formatter ...@@ -390,7 +393,6 @@ class i_formatter SPDLOG_FINAL : public flag_formatter
{ {
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{ {
fmt_helper::pad6(msg.msg_id, dest); fmt_helper::pad6(msg.msg_id, dest);
} }
}; };
...@@ -462,39 +464,48 @@ class full_formatter SPDLOG_FINAL : public flag_formatter ...@@ -462,39 +464,48 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
{ {
#ifndef SPDLOG_NO_DATETIME #ifndef SPDLOG_NO_DATETIME
// each second cache the header // cache the date/time part for the next second.
auto duration = msg.time.time_since_epoch(); auto duration = msg.time.time_since_epoch();
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count(); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
if (cached_header_.size() == 0 || cached_seconds_ts_ != seconds)
if (cache_timestamp_ != seconds || cached_datetime_.size() == 0)
{ {
cached_header_ = fmt::memory_buffer(); cached_datetime_.resize(0);
cached_header_.push_back('['); cached_datetime_.push_back('[');
fmt_helper::append_int(tm_time.tm_year + 1900, cached_header_); fmt_helper::append_int(tm_time.tm_year + 1900, cached_datetime_);
cached_header_.push_back('-'); cached_datetime_.push_back('-');
fmt_helper::pad2(tm_time.tm_mon + 1, cached_header_); fmt_helper::pad2(tm_time.tm_mon + 1, cached_datetime_);
cached_header_.push_back('-'); cached_datetime_.push_back('-');
fmt_helper::pad2(tm_time.tm_mday, cached_header_); fmt_helper::pad2(tm_time.tm_mday, cached_datetime_);
cached_header_.push_back(' '); cached_datetime_.push_back(' ');
fmt_helper::pad2(tm_time.tm_hour, cached_header_); fmt_helper::pad2(tm_time.tm_hour, cached_datetime_);
cached_header_.push_back(':'); cached_datetime_.push_back(':');
fmt_helper::pad2(tm_time.tm_min, cached_header_); fmt_helper::pad2(tm_time.tm_min, cached_datetime_);
cached_header_.push_back(':'); cached_datetime_.push_back(':');
fmt_helper::pad2(tm_time.tm_sec, cached_header_); fmt_helper::pad2(tm_time.tm_sec, cached_datetime_);
cached_header_.push_back('.'); cached_datetime_.push_back('.');
cached_seconds_ts_ = seconds; cache_timestamp_ = seconds;
} }
fmt_helper::append_buf(cached_header_, dest); fmt_helper::append_buf(cached_datetime_, dest);
// cache the millis part for the next milli.
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000; auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
fmt_helper::pad3(static_cast<int>(millis), dest); if(millis != millis_cache_timestamp_ || cached_millis_.size() == 0)
dest.push_back(']'); {
dest.push_back(' '); cached_millis_.resize(0);
fmt_helper::pad3(millis, cached_millis_);
cached_millis_.push_back(']');
cached_millis_.push_back(' ');
millis_cache_timestamp_ = millis;
}
fmt_helper::append_buf(cached_millis_, dest);
#else // no datetime needed #else // no datetime needed
(void)tm_time; (void)tm_time;
#endif #endif
...@@ -517,8 +528,10 @@ class full_formatter SPDLOG_FINAL : public flag_formatter ...@@ -517,8 +528,10 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
} }
private: private:
std::chrono::seconds::rep cached_seconds_ts_{0}; std::chrono::seconds cache_timestamp_ {0};
fmt::memory_buffer cached_header_; std::chrono::milliseconds::rep millis_cache_timestamp_ {0};
fmt::basic_memory_buffer<char, 128> cached_datetime_;
fmt::basic_memory_buffer<char, 8> cached_millis_;
}; };
} // namespace details } // namespace details
...@@ -526,14 +539,14 @@ private: ...@@ -526,14 +539,14 @@ private:
class pattern_formatter SPDLOG_FINAL : public formatter class pattern_formatter SPDLOG_FINAL : public formatter
{ {
public: public:
explicit pattern_formatter(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local, explicit pattern_formatter(const std::string &pattern, pattern_time_type time_type = pattern_time_type::local,
std::string eol = spdlog::details::os::default_eol) std::string eol = spdlog::details::os::default_eol)
: eol_(std::move(eol)) : eol_(std::move(eol))
, pattern_time_(pattern_time) , pattern_time_type_(time_type)
, last_log_secs_(0) , last_log_secs_(0)
{ {
std::memset(&cached_tm_, 0, sizeof(cached_tm_)); std::memset(&cached_tm_, 0, sizeof(cached_tm_));
compile_pattern(pattern); compile_pattern_(pattern);
} }
pattern_formatter(const pattern_formatter &) = default; pattern_formatter(const pattern_formatter &) = default;
...@@ -544,7 +557,7 @@ public: ...@@ -544,7 +557,7 @@ public:
auto secs = std::chrono::duration_cast<std::chrono::seconds>(msg.time.time_since_epoch()); auto secs = std::chrono::duration_cast<std::chrono::seconds>(msg.time.time_since_epoch());
if (secs != last_log_secs_) if (secs != last_log_secs_)
{ {
cached_tm_ = get_time(msg); cached_tm_ = get_time_(msg);
last_log_secs_ = secs; last_log_secs_ = secs;
} }
#endif #endif
...@@ -558,21 +571,22 @@ public: ...@@ -558,21 +571,22 @@ public:
private: private:
const std::string eol_; const std::string eol_;
const pattern_time_type pattern_time_; pattern_time_type pattern_time_type_;
std::tm cached_tm_; std::tm cached_tm_;
std::chrono::seconds last_log_secs_; std::chrono::seconds last_log_secs_;
std::vector<std::unique_ptr<details::flag_formatter>> formatters_; std::vector<std::unique_ptr<details::flag_formatter>> formatters_;
std::tm get_time(const details::log_msg &msg)
std::tm get_time_(const details::log_msg &msg)
{ {
if (pattern_time_ == pattern_time_type::local) if (pattern_time_type_ == pattern_time_type::local)
{ {
return details::os::localtime(log_clock::to_time_t(msg.time)); return details::os::localtime(log_clock::to_time_t(msg.time));
} }
return details::os::gmtime(log_clock::to_time_t(msg.time)); return details::os::gmtime(log_clock::to_time_t(msg.time));
} }
void handle_flag(char flag) void handle_flag_(char flag)
{ {
switch (flag) switch (flag)
{ {
...@@ -717,7 +731,7 @@ private: ...@@ -717,7 +731,7 @@ private:
} }
} }
void compile_pattern(const std::string &pattern) void compile_pattern_(const std::string &pattern)
{ {
auto end = pattern.end(); auto end = pattern.end();
std::unique_ptr<details::aggregate_formatter> user_chars; std::unique_ptr<details::aggregate_formatter> user_chars;
...@@ -732,7 +746,7 @@ private: ...@@ -732,7 +746,7 @@ private:
// if( // if(
if (++it != end) if (++it != end)
{ {
handle_flag(*it); handle_flag_(*it);
} }
else else
{ {
......
...@@ -36,7 +36,7 @@ public: ...@@ -36,7 +36,7 @@ public:
{ {
std::lock_guard<Mutex> lock(mutex_); std::lock_guard<Mutex> lock(mutex_);
auto logger_name = new_logger->name(); auto logger_name = new_logger->name();
throw_if_exists(logger_name); throw_if_exists_(logger_name);
loggers_[logger_name] = new_logger; loggers_[logger_name] = new_logger;
} }
...@@ -44,11 +44,11 @@ public: ...@@ -44,11 +44,11 @@ public:
{ {
std::lock_guard<Mutex> lock(mutex_); std::lock_guard<Mutex> lock(mutex_);
auto logger_name = new_logger->name(); auto logger_name = new_logger->name();
throw_if_exists(logger_name); throw_if_exists_(logger_name);
// create default formatter if not exists // create default formatter if not exists
new_logger->set_pattern(formatter_pattern_); new_logger->set_formatter<pattern_formatter>(formatter_pattern_, pattern_time_type_);
if (err_handler_) if (err_handler_)
{ {
...@@ -81,13 +81,14 @@ public: ...@@ -81,13 +81,14 @@ public:
return tp_; return tp_;
} }
void set_pattern(const std::string &pattern) void set_pattern(const std::string &pattern, pattern_time_type time_type)
{ {
std::lock_guard<Mutex> lock(mutex_); std::lock_guard<Mutex> lock(mutex_);
formatter_pattern_ = pattern; formatter_pattern_ = pattern;
pattern_time_type_ = time_type;
for (auto &l : loggers_) for (auto &l : loggers_)
{ {
l.second->set_pattern(pattern); l.second->set_pattern(pattern, time_type);
} }
} }
...@@ -162,7 +163,7 @@ public: ...@@ -162,7 +163,7 @@ public:
private: private:
registry_t<Mutex>() = default; registry_t<Mutex>() = default;
void throw_if_exists(const std::string &logger_name) void throw_if_exists_(const std::string &logger_name)
{ {
if (loggers_.find(logger_name) != loggers_.end()) if (loggers_.find(logger_name) != loggers_.end())
{ {
...@@ -174,6 +175,7 @@ private: ...@@ -174,6 +175,7 @@ private:
Mutex tp_mutex_; Mutex tp_mutex_;
std::unordered_map<std::string, std::shared_ptr<logger>> loggers_; std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;
std::string formatter_pattern_ = "%+"; std::string formatter_pattern_ = "%+";
pattern_time_type pattern_time_type_ = pattern_time_type::local;
level::level_enum level_ = level::info; level::level_enum level_ = level::info;
level::level_enum flush_level_ = level::off; level::level_enum flush_level_ = level::off;
log_err_handler err_handler_; log_err_handler err_handler_;
......
...@@ -29,7 +29,7 @@ struct async_msg ...@@ -29,7 +29,7 @@ struct async_msg
level::level_enum level; level::level_enum level;
log_clock::time_point time; log_clock::time_point time;
size_t thread_id; size_t thread_id;
fmt::basic_memory_buffer<char, 128> raw; fmt::basic_memory_buffer<char, 176> raw;
size_t msg_id; size_t msg_id;
async_logger_ptr worker_ptr; async_logger_ptr worker_ptr;
...@@ -95,7 +95,7 @@ public: ...@@ -95,7 +95,7 @@ public:
} }
for (size_t i = 0; i < threads_n; i++) for (size_t i = 0; i < threads_n; i++)
{ {
threads_.emplace_back(std::bind(&thread_pool::worker_loop, this)); threads_.emplace_back(std::bind(&thread_pool::worker_loop_, this));
} }
} }
...@@ -106,14 +106,13 @@ public: ...@@ -106,14 +106,13 @@ public:
{ {
for (size_t i = 0; i < threads_.size(); i++) for (size_t i = 0; i < threads_.size(); i++)
{ {
post_async_msg(async_msg(async_msg_type::terminate), async_overflow_policy::block_retry); post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block);
} }
for (auto &t : threads_) for (auto &t : threads_)
{ {
t.join(); t.join();
} }
// std::cout << "~thread_pool() msg_counter_: " << msg_counter_ << std::endl;
} }
catch (...) catch (...)
{ {
...@@ -123,12 +122,12 @@ public: ...@@ -123,12 +122,12 @@ public:
void post_log(async_logger_ptr &&worker_ptr, details::log_msg &&msg, async_overflow_policy overflow_policy) void post_log(async_logger_ptr &&worker_ptr, details::log_msg &&msg, async_overflow_policy overflow_policy)
{ {
async_msg async_m(std::forward<async_logger_ptr>(worker_ptr), async_msg_type::log, std::forward<log_msg>(msg)); async_msg async_m(std::forward<async_logger_ptr>(worker_ptr), async_msg_type::log, std::forward<log_msg>(msg));
post_async_msg(std::move(async_m), overflow_policy); post_async_msg_(std::move(async_m), overflow_policy);
} }
void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy) void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy)
{ {
post_async_msg(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy); post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy);
} }
private: private:
...@@ -136,9 +135,9 @@ private: ...@@ -136,9 +135,9 @@ private:
std::vector<std::thread> threads_; std::vector<std::thread> threads_;
void post_async_msg(async_msg &&new_msg, async_overflow_policy overflow_policy) void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy)
{ {
if (overflow_policy == async_overflow_policy::block_retry) if (overflow_policy == async_overflow_policy::block)
{ {
q_.enqueue(std::move(new_msg)); q_.enqueue(std::move(new_msg));
} }
...@@ -148,14 +147,14 @@ private: ...@@ -148,14 +147,14 @@ private:
} }
} }
void worker_loop() void worker_loop_()
{ {
while (process_next_msg()) {}; while (process_next_msg_()) {};
} }
// process next message in the queue // process next message in the queue
// return true if this thread should still be active (while no terminate msg was received) // return true if this thread should still be active (while no terminate msg was received)
bool process_next_msg() bool process_next_msg_()
{ {
async_msg incoming_async_msg; async_msg incoming_async_msg;
bool dequeued = q_.dequeue_for(incoming_async_msg, std::chrono::seconds(10)); bool dequeued = q_.dequeue_for(incoming_async_msg, std::chrono::seconds(10));
......
...@@ -196,12 +196,22 @@ ...@@ -196,12 +196,22 @@
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
// An implementation of declval for pre-C++11 compilers such as gcc 4.
namespace internal { namespace internal {
// An implementation of declval for pre-C++11 compilers such as gcc 4.
template<typename T> template<typename T>
typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT; typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT;
// Casts nonnegative integer to unsigned.
template<typename Int>
FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value)
{
FMT_ASSERT(value >= 0, "negative value");
return static_cast<typename std::make_unsigned<Int>::type>(value);
} }
} // namespace internal
/** /**
An implementation of ``std::basic_string_view`` for pre-C++17. It provides a An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
subset of the API. ``fmt::basic_string_view`` is used for format strings even subset of the API. ``fmt::basic_string_view`` is used for format strings even
...@@ -242,7 +252,7 @@ public: ...@@ -242,7 +252,7 @@ public:
FMT_CONSTEXPR basic_string_view() FMT_NOEXCEPT : data_(FMT_NULL), size_(0) {} FMT_CONSTEXPR basic_string_view() FMT_NOEXCEPT : data_(FMT_NULL), size_(0) {}
/** Constructs a string reference object from a C string and a size. */ /** Constructs a string reference object from a C string and a size. */
FMT_CONSTEXPR basic_string_view(const Char *s, size_t str_size) FMT_NOEXCEPT : data_(s), size_(str_size) {} FMT_CONSTEXPR basic_string_view(const Char *s, size_t count) FMT_NOEXCEPT : data_(s), size_(count) {}
/** /**
\rst \rst
...@@ -354,11 +364,7 @@ private: ...@@ -354,11 +364,7 @@ private:
std::size_t capacity_; std::size_t capacity_;
protected: protected:
basic_buffer(T *p = FMT_NULL, std::size_t buf_size = 0, std::size_t buf_capacity = 0) FMT_NOEXCEPT : ptr_(p), basic_buffer(T *p = FMT_NULL, std::size_t sz = 0, std::size_t cap = 0) FMT_NOEXCEPT : ptr_(p), size_(sz), capacity_(cap) {}
size_(buf_size),
capacity_(buf_capacity)
{
}
/** Sets the buffer data and capacity. */ /** Sets the buffer data and capacity. */
void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT
...@@ -418,11 +424,11 @@ public: ...@@ -418,11 +424,11 @@ public:
size_ = new_size; size_ = new_size;
} }
/** Reserves space to store at least *buf_capacity* elements. */ /** Reserves space to store at least *capacity* elements. */
void reserve(std::size_t buf_capacity) void reserve(std::size_t new_capacity)
{ {
if (buf_capacity > capacity_) if (new_capacity > capacity_)
grow(buf_capacity); grow(new_capacity);
} }
void push_back(const T &value) void push_back(const T &value)
...@@ -893,7 +899,7 @@ public: ...@@ -893,7 +899,7 @@ public:
// Advances the begin iterator to ``it``. // Advances the begin iterator to ``it``.
FMT_CONSTEXPR void advance_to(iterator it) FMT_CONSTEXPR void advance_to(iterator it)
{ {
format_str_.remove_prefix(it - begin()); format_str_.remove_prefix(internal::to_unsigned(it - begin()));
} }
// Returns the next argument index. // Returns the next argument index.
...@@ -1135,13 +1141,13 @@ struct get_type ...@@ -1135,13 +1141,13 @@ struct get_type
}; };
template<typename Context> template<typename Context>
FMT_CONSTEXPR uint64_t get_types() FMT_CONSTEXPR unsigned long long get_types()
{ {
return 0; return 0;
} }
template<typename Context, typename Arg, typename... Args> template<typename Context, typename Arg, typename... Args>
FMT_CONSTEXPR uint64_t get_types() FMT_CONSTEXPR unsigned long long get_types()
{ {
return get_type<Context, Arg>::value | (get_types<Context, Args...>() << 4); return get_type<Context, Arg>::value | (get_types<Context, Args...>() << 4);
} }
...@@ -1187,27 +1193,29 @@ private: ...@@ -1187,27 +1193,29 @@ private:
typedef typename std::conditional<IS_PACKED, internal::value<Context>, basic_format_arg<Context>>::type value_type; typedef typename std::conditional<IS_PACKED, internal::value<Context>, basic_format_arg<Context>>::type value_type;
// If the arguments are not packed, add one more element to mark the end. // If the arguments are not packed, add one more element to mark the end.
value_type data_[NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1)]; static const size_t DATA_SIZE = NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1);
value_type data_[DATA_SIZE];
friend class basic_format_args<Context>; friend class basic_format_args<Context>;
static FMT_CONSTEXPR int64_t get_types() static FMT_CONSTEXPR long long get_types()
{ {
return IS_PACKED ? static_cast<int64_t>(internal::get_types<Context, Args...>()) : -static_cast<int64_t>(NUM_ARGS); return IS_PACKED ? static_cast<long long>(internal::get_types<Context, Args...>()) : -static_cast<long long>(NUM_ARGS);
} }
public: public:
#if FMT_USE_CONSTEXPR #if FMT_USE_CONSTEXPR
static constexpr int64_t TYPES = get_types(); static constexpr long long TYPES = get_types();
#else #else
static const int64_t TYPES; static const long long TYPES;
#endif #endif
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405 #if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 405) || (FMT_MSC_VER && FMT_MSC_VER <= 1800)
// Workaround an array initialization bug in gcc 4.5 and earlier. // Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013.
format_arg_store(const Args &... args) format_arg_store(const Args &... args)
{ {
data_ = {internal::make_arg<IS_PACKED, Context>(args)...}; value_type init[DATA_SIZE] = {internal::make_arg<IS_PACKED, Context>(args)...};
std::memcpy(data_, init, sizeof(init));
} }
#else #else
format_arg_store(const Args &... args) format_arg_store(const Args &... args)
...@@ -1219,7 +1227,7 @@ public: ...@@ -1219,7 +1227,7 @@ public:
#if !FMT_USE_CONSTEXPR #if !FMT_USE_CONSTEXPR
template<typename Context, typename... Args> template<typename Context, typename... Args>
const int64_t format_arg_store<Context, Args...>::TYPES = get_types(); const long long format_arg_store<Context, Args...>::TYPES = get_types();
#endif #endif
/** /**
...@@ -1252,7 +1260,7 @@ public: ...@@ -1252,7 +1260,7 @@ public:
private: private:
// To reduce compiled code size per formatting function call, types of first // To reduce compiled code size per formatting function call, types of first
// max_packed_args arguments are passed in the types_ field. // max_packed_args arguments are passed in the types_ field.
uint64_t types_; unsigned long long types_;
union union
{ {
// If the number of arguments is less than max_packed_args, the argument // If the number of arguments is less than max_packed_args, the argument
...@@ -1267,7 +1275,7 @@ private: ...@@ -1267,7 +1275,7 @@ private:
typename internal::type type(unsigned index) const typename internal::type type(unsigned index) const
{ {
unsigned shift = index * 4; unsigned shift = index * 4;
uint64_t mask = 0xf; unsigned long long mask = 0xf;
return static_cast<typename internal::type>((types_ & (mask << shift)) >> shift); return static_cast<typename internal::type>((types_ & (mask << shift)) >> shift);
} }
...@@ -1284,10 +1292,10 @@ private: ...@@ -1284,10 +1292,10 @@ private:
format_arg do_get(size_type index) const format_arg do_get(size_type index) const
{ {
int64_t signed_types = static_cast<int64_t>(types_); long long signed_types = static_cast<long long>(types_);
if (signed_types < 0) if (signed_types < 0)
{ {
uint64_t num_args = -signed_types; unsigned long long num_args = static_cast<unsigned long long>(-signed_types);
return index < num_args ? args_[index] : format_arg(); return index < num_args ? args_[index] : format_arg();
} }
format_arg arg; format_arg arg;
...@@ -1314,7 +1322,7 @@ public: ...@@ -1314,7 +1322,7 @@ public:
*/ */
template<typename... Args> template<typename... Args>
basic_format_args(const format_arg_store<Context, Args...> &store) basic_format_args(const format_arg_store<Context, Args...> &store)
: types_(store.TYPES) : types_(static_cast<unsigned long long>(store.TYPES))
{ {
set_data(store.data_); set_data(store.data_);
} }
...@@ -1328,8 +1336,8 @@ public: ...@@ -1328,8 +1336,8 @@ public:
unsigned max_size() const unsigned max_size() const
{ {
int64_t signed_types = static_cast<int64_t>(types_); long long signed_types = static_cast<long long>(types_);
return static_cast<unsigned>(signed_types < 0 ? -signed_types : static_cast<int64_t>(internal::max_packed_args)); return static_cast<unsigned>(signed_types < 0 ? -signed_types : static_cast<long long>(internal::max_packed_args));
} }
}; };
...@@ -1414,6 +1422,8 @@ inline internal::named_arg<T, wchar_t> arg(wstring_view name, const T &arg) ...@@ -1414,6 +1422,8 @@ inline internal::named_arg<T, wchar_t> arg(wstring_view name, const T &arg)
template<typename S, typename T, typename Char> template<typename S, typename T, typename Char>
void arg(S, internal::named_arg<T, Char>) FMT_DELETED; void arg(S, internal::named_arg<T, Char>) FMT_DELETED;
#ifndef FMT_EXTENDED_COLORS
// color and (v)print_colored are deprecated.
enum color enum color
{ {
black, black,
...@@ -1425,27 +1435,19 @@ enum color ...@@ -1425,27 +1435,19 @@ enum color
cyan, cyan,
white white
}; };
FMT_API void vprint_colored(color c, string_view format, format_args args); FMT_API void vprint_colored(color c, string_view format, format_args args);
FMT_API void vprint_colored(color c, wstring_view format, wformat_args args); FMT_API void vprint_colored(color c, wstring_view format, wformat_args args);
/**
Formats a string and prints it to stdout using ANSI escape sequences to
specify color (experimental).
Example:
fmt::print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23);
*/
template<typename... Args> template<typename... Args>
inline void print_colored(color c, string_view format_str, const Args &... args) inline void print_colored(color c, string_view format_str, const Args &... args)
{ {
vprint_colored(c, format_str, make_format_args(args...)); vprint_colored(c, format_str, make_format_args(args...));
} }
template<typename... Args> template<typename... Args>
inline void print_colored(color c, wstring_view format_str, const Args &... args) inline void print_colored(color c, wstring_view format_str, const Args &... args)
{ {
vprint_colored(c, format_str, make_format_args<wformat_context>(args...)); vprint_colored(c, format_str, make_format_args<wformat_context>(args...));
} }
#endif
format_context::iterator vformat_to(internal::buffer &buf, string_view format_str, format_args args); format_context::iterator vformat_to(internal::buffer &buf, string_view format_str, format_args args);
wformat_context::iterator vformat_to(internal::wbuffer &buf, wstring_view format_str, wformat_args args); wformat_context::iterator vformat_to(internal::wbuffer &buf, wstring_view format_str, wformat_args args);
......
...@@ -89,9 +89,6 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) ...@@ -89,9 +89,6 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...)
#define FMT_SWPRINTF swprintf #define FMT_SWPRINTF swprintf
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) #endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
const char RESET_COLOR[] = "\x1b[0m";
const wchar_t WRESET_COLOR[] = L"\x1b[0m";
typedef void (*FormatFunc)(internal::buffer &, int, string_view); typedef void (*FormatFunc)(internal::buffer &, int, string_view);
// Portable thread-safe version of strerror. // Portable thread-safe version of strerror.
...@@ -300,6 +297,11 @@ const int16_t basic_data<T>::POW10_EXPONENTS[] = {-1220, -1193, -1166, -1140, -1 ...@@ -300,6 +297,11 @@ const int16_t basic_data<T>::POW10_EXPONENTS[] = {-1220, -1193, -1166, -1140, -1
-289, -263, -236, -210, -183, -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, 375, -289, -263, -236, -210, -183, -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, 375,
402, 428, 455, 481, 508, 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066}; 402, 428, 455, 481, 508, 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066};
template<typename T>
const char basic_data<T>::RESET_COLOR[] = "\x1b[0m";
template<typename T>
const wchar_t basic_data<T>::WRESET_COLOR[] = L"\x1b[0m";
FMT_FUNC fp operator*(fp x, fp y) FMT_FUNC fp operator*(fp x, fp y)
{ {
// Multiply 32-bit parts of significands. // Multiply 32-bit parts of significands.
...@@ -502,13 +504,14 @@ FMT_FUNC void vprint(wstring_view format_str, wformat_args args) ...@@ -502,13 +504,14 @@ FMT_FUNC void vprint(wstring_view format_str, wformat_args args)
vprint(stdout, format_str, args); vprint(stdout, format_str, args);
} }
#ifndef FMT_EXTENDED_COLORS
FMT_FUNC void vprint_colored(color c, string_view format, format_args args) FMT_FUNC void vprint_colored(color c, string_view format, format_args args)
{ {
char escape[] = "\x1b[30m"; char escape[] = "\x1b[30m";
escape[3] = static_cast<char>('0' + c); escape[3] = static_cast<char>('0' + c);
std::fputs(escape, stdout); std::fputs(escape, stdout);
vprint(format, args); vprint(format, args);
std::fputs(RESET_COLOR, stdout); std::fputs(internal::data::RESET_COLOR, stdout);
} }
FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args) FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args)
...@@ -517,8 +520,48 @@ FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args) ...@@ -517,8 +520,48 @@ FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args)
escape[3] = static_cast<wchar_t>('0' + c); escape[3] = static_cast<wchar_t>('0' + c);
std::fputws(escape, stdout); std::fputws(escape, stdout);
vprint(format, args); vprint(format, args);
std::fputws(WRESET_COLOR, stdout); std::fputws(internal::data::WRESET_COLOR, stdout);
}
#else
namespace internal {
FMT_CONSTEXPR void to_esc(uint8_t c, char out[], int offset)
{
out[offset + 0] = static_cast<char>('0' + c / 100);
out[offset + 1] = static_cast<char>('0' + c / 10 % 10);
out[offset + 2] = static_cast<char>('0' + c % 10);
} }
} // namespace internal
FMT_FUNC void vprint_rgb(rgb fd, string_view format, format_args args)
{
char escape_fd[] = "\x1b[38;2;000;000;000m";
internal::to_esc(fd.r, escape_fd, 7);
internal::to_esc(fd.g, escape_fd, 11);
internal::to_esc(fd.b, escape_fd, 15);
std::fputs(escape_fd, stdout);
vprint(format, args);
std::fputs(internal::data::RESET_COLOR, stdout);
}
FMT_FUNC void vprint_rgb(rgb fd, rgb bg, string_view format, format_args args)
{
char escape_fd[] = "\x1b[38;2;000;000;000m"; // foreground color
char escape_bg[] = "\x1b[48;2;000;000;000m"; // background color
internal::to_esc(fd.r, escape_fd, 7);
internal::to_esc(fd.g, escape_fd, 11);
internal::to_esc(fd.b, escape_fd, 15);
internal::to_esc(bg.r, escape_bg, 7);
internal::to_esc(bg.g, escape_bg, 11);
internal::to_esc(bg.b, escape_bg, 15);
std::fputs(escape_fd, stdout);
std::fputs(escape_bg, stdout);
vprint(format, args);
std::fputs(internal::data::RESET_COLOR, stdout);
}
#endif
FMT_FUNC locale locale_provider::locale() FMT_FUNC locale locale_provider::locale()
{ {
......
// Formatting library for C++
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#include "fmt/format-inl.h"
namespace fmt {
template struct internal::basic_data<void>;
// Explicit instantiations for char.
template FMT_API char internal::thousands_sep(locale_provider *lp);
template void basic_fixed_buffer<char>::grow(std::size_t);
template void internal::arg_map<format_context>::init(
const basic_format_args<format_context> &args);
template FMT_API int internal::char_traits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, double value);
template FMT_API int internal::char_traits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, long double value);
// Explicit instantiations for wchar_t.
template FMT_API wchar_t internal::thousands_sep(locale_provider *lp);
template void basic_fixed_buffer<wchar_t>::grow(std::size_t);
template void internal::arg_map<wformat_context>::init(const wformat_args &args);
template FMT_API int internal::char_traits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, double value);
template FMT_API int internal::char_traits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, long double value);
} // namespace fmt
This diff is collapsed.
...@@ -290,27 +290,38 @@ public: ...@@ -290,27 +290,38 @@ public:
{ {
} }
using base::operator(); template<typename T>
typename std::enable_if<std::is_integral<T>::value, iterator>::type operator()(T value)
/** Formats an argument of type ``bool``. */
iterator operator()(bool value)
{ {
format_specs &fmt_spec = this->spec(); // MSVC2013 fails to compile separate overloads for bool and char_type so
if (fmt_spec.type_ != 's') // use std::is_same instead.
return (*this)(value ? 1 : 0); if (std::is_same<T, bool>::value)
fmt_spec.type_ = 0; {
this->write(value); format_specs &fmt_spec = this->spec();
if (fmt_spec.type_ != 's')
return base::operator()(value ? 1 : 0);
fmt_spec.type_ = 0;
this->write(value != 0);
}
else if (std::is_same<T, char_type>::value)
{
format_specs &fmt_spec = this->spec();
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
return (*this)(static_cast<int>(value));
fmt_spec.flags_ = 0;
fmt_spec.align_ = ALIGN_RIGHT;
return base::operator()(value);
}
else
{
return base::operator()(value);
}
return this->out(); return this->out();
} }
/** Formats a character. */ template<typename T>
iterator operator()(char_type value) typename std::enable_if<std::is_floating_point<T>::value, iterator>::type operator()(T value)
{ {
format_specs &fmt_spec = this->spec();
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
return (*this)(static_cast<int>(value));
fmt_spec.flags_ = 0;
fmt_spec.align_ = ALIGN_RIGHT;
return base::operator()(value); return base::operator()(value);
} }
...@@ -338,6 +349,16 @@ public: ...@@ -338,6 +349,16 @@ public:
return this->out(); return this->out();
} }
iterator operator()(basic_string_view<char_type> value)
{
return base::operator()(value);
}
iterator operator()(monostate value)
{
return base::operator()(value);
}
/** Formats a pointer. */ /** Formats a pointer. */
iterator operator()(const void *value) iterator operator()(const void *value)
{ {
......
...@@ -114,12 +114,14 @@ struct is_range_ : std::false_type ...@@ -114,12 +114,14 @@ struct is_range_ : std::false_type
{ {
}; };
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
template<typename T> template<typename T>
struct is_range_<T, typename std::conditional<false, struct is_range_<T, typename std::conditional<false,
conditional_helper<decltype(internal::declval<T>().begin()), decltype(internal::declval<T>().end())>, void>::type> conditional_helper<decltype(internal::declval<T>().begin()), decltype(internal::declval<T>().end())>, void>::type>
: std::true_type : std::true_type
{ {
}; };
#endif
/// tuple_size and tuple_element check. /// tuple_size and tuple_element check.
template<typename T> template<typename T>
...@@ -171,7 +173,7 @@ using make_index_sequence = make_integer_sequence<std::size_t, N>; ...@@ -171,7 +173,7 @@ using make_index_sequence = make_integer_sequence<std::size_t, N>;
#endif #endif
template<class Tuple, class F, size_t... Is> template<class Tuple, class F, size_t... Is>
void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) noexcept void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) FMT_NOEXCEPT
{ {
using std::get; using std::get;
// using free function get<I>(T) now. // using free function get<I>(T) now.
......
...@@ -17,5 +17,3 @@ public: ...@@ -17,5 +17,3 @@ public:
virtual void format(const details::log_msg &msg, fmt::memory_buffer &dest) = 0; virtual void format(const details::log_msg &msg, fmt::memory_buffer &dest) = 0;
}; };
} // namespace spdlog } // namespace spdlog
#include "details/pattern_formatter_impl.h"
...@@ -45,23 +45,23 @@ public: ...@@ -45,23 +45,23 @@ public:
template<typename... Args> template<typename... Args>
void log(level::level_enum lvl, const char *msg); void log(level::level_enum lvl, const char *msg);
template<typename Arg1, typename... Args> template<typename... Args>
void trace(const char *fmt, const Arg1 &, const Args &... args); void trace(const char *fmt, const Args &... args);
template<typename Arg1, typename... Args> template<typename... Args>
void debug(const char *fmt, const Arg1 &, const Args &... args); void debug(const char *fmt, const Args &... args);
template<typename Arg1, typename... Args> template<typename... Args>
void info(const char *fmt, const Arg1 &, const Args &... args); void info(const char *fmt, const Args &... args);
template<typename Arg1, typename... Args> template<typename... Args>
void warn(const char *fmt, const Arg1 &, const Args &... args); void warn(const char *fmt, const Args &... args);
template<typename Arg1, typename... Args> template<typename... Args>
void error(const char *fmt, const Arg1 &, const Args &... args); void error(const char *fmt, const Args &... args);
template<typename Arg1, typename... Args> template<typename... Args>
void critical(const char *fmt, const Arg1 &, const Args &... args); void critical(const char *fmt, const Args &... args);
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
template<typename... Args> template<typename... Args>
...@@ -117,10 +117,10 @@ public: ...@@ -117,10 +117,10 @@ public:
// create a pattern formatter all the sinks in this logger. // create a pattern formatter all the sinks in this logger.
// each sink gets itw own private copy of a formatter object. // each sink gets itw own private copy of a formatter object.
void set_pattern(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local); void set_pattern(const std::string &pattern, pattern_time_type time_type = pattern_time_type::local);
// create a FormatterT formatter all the sinks in this logger. // create a FormatterT formatter for each sink in this logger.
// each sink gets itw own private copy of a formatter object. // each sink gets its own private copy of a formatter object.
template<class FormatterT, typename... Args> template<class FormatterT, typename... Args>
void set_formatter(const Args &... args); void set_formatter(const Args &... args);
......
...@@ -38,7 +38,7 @@ public: ...@@ -38,7 +38,7 @@ public:
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 android_LogPriority priority = convert_to_android_(msg.level);
fmt::memory_buffer formatted; fmt::memory_buffer formatted;
if (use_raw_msg_) if (use_raw_msg_)
{ {
...@@ -70,7 +70,7 @@ public: ...@@ -70,7 +70,7 @@ public:
void flush() override {} void flush() override {}
private: private:
static android_LogPriority convert_to_android(spdlog::level::level_enum level) static android_LogPriority convert_to_android_(spdlog::level::level_enum level)
{ {
switch (level) switch (level)
{ {
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
#pragma once #pragma once
#include "spdlog/details/console_globals.h"
#include "spdlog/details/null_mutex.h" #include "spdlog/details/null_mutex.h"
#include "spdlog/details/os.h" #include "spdlog/details/os.h"
#include "spdlog/details/traits.h"
#include <memory> #include <memory>
#include <mutex> #include <mutex>
...@@ -22,14 +22,14 @@ namespace sinks { ...@@ -22,14 +22,14 @@ namespace sinks {
* of the message. * of the message.
* If no color terminal detected, omit the escape codes. * If no color terminal detected, omit the escape codes.
*/ */
template<class StreamTrait, class ConsoleMutexTrait> template<class TargetStream, class ConsoleMutex>
class ansicolor_sink : public sink class ansicolor_sink : public sink
{ {
public: public:
using mutex_t = typename ConsoleMutexTrait::mutex_t; using mutex_t = typename ConsoleMutex::mutex_t;
ansicolor_sink() ansicolor_sink()
: target_file_(StreamTrait::stream()) : target_file_(TargetStream::stream())
, mutex_(ConsoleMutexTrait::console_mutex()) , mutex_(ConsoleMutex::console_mutex())
{ {
should_do_colors_ = details::os::in_terminal(target_file_) && details::os::is_color_terminal(); should_do_colors_ = details::os::in_terminal(target_file_) && details::os::is_color_terminal();
...@@ -132,10 +132,11 @@ private: ...@@ -132,10 +132,11 @@ private:
std::unordered_map<level::level_enum, std::string, level::level_hasher> colors_; std::unordered_map<level::level_enum, std::string, level::level_hasher> colors_;
}; };
using ansicolor_stdout_sink_mt = ansicolor_sink<details::console_stdout_trait, details::console_mutex_trait>; using ansicolor_stdout_sink_mt = ansicolor_sink<details::console_stdout_stream, details::console_global_mutex>;
using ansicolor_stdout_sink_st = ansicolor_sink<details::console_stdout_trait, details::console_null_mutex_trait>; using ansicolor_stdout_sink_st = ansicolor_sink<details::console_stdout_stream, details::console_global_nullmutex>;
using ansicolor_stderr_sink_mt = ansicolor_sink<details::console_stderr_trait, details::console_mutex_trait>;
using ansicolor_stderr_sink_st = ansicolor_sink<details::console_stderr_trait, details::console_null_mutex_trait>; using ansicolor_stderr_sink_mt = ansicolor_sink<details::console_stderr_stream, details::console_global_mutex>;
using ansicolor_stderr_sink_st = ansicolor_sink<details::console_stderr_stream, details::console_global_nullmutex>;
} // namespace sinks } // namespace sinks
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
#pragma once #pragma once
// //
// base sink templated over a mutex (either dummy or real) // base sink templated over a mutex (either dummy or real)
// concrete implementation should only override the sink_it_ method. // concrete implementation should override the sink_it_() and flush_() methods.
// all locking is taken care of here so no locking needed by the implementers.. // locking is taken care of in this class - no locking needed by the implementers..
// //
#include "spdlog/common.h" #include "spdlog/common.h"
...@@ -26,16 +26,6 @@ public: ...@@ -26,16 +26,6 @@ public:
{ {
} }
base_sink(const std::string &formatter_pattern)
: sink(formatter_pattern)
{
}
base_sink(std::unique_ptr<spdlog::formatter> sink_formatter)
: sink(std::move(sink_formatter))
{
}
base_sink(const base_sink &) = delete; base_sink(const base_sink &) = delete;
base_sink &operator=(const base_sink &) = delete; base_sink &operator=(const base_sink &) = delete;
......
...@@ -18,28 +18,18 @@ namespace sinks { ...@@ -18,28 +18,18 @@ namespace sinks {
* Trivial file sink with single file as target * Trivial file sink with single file as target
*/ */
template<class Mutex> template<class Mutex>
class simple_file_sink SPDLOG_FINAL : public base_sink<Mutex> class basic_file_sink SPDLOG_FINAL : public base_sink<Mutex>
{ {
public: public:
explicit simple_file_sink(const filename_t &filename, bool truncate = false) explicit basic_file_sink(const filename_t &filename, bool truncate = false)
: force_flush_(false)
{ {
file_helper_.open(filename, truncate); file_helper_.open(filename, truncate);
} }
void set_force_flush(bool force_flush)
{
force_flush_ = force_flush;
}
protected: protected:
void sink_it_(const details::log_msg &, const fmt::memory_buffer &formatted) override void sink_it_(const details::log_msg &, const fmt::memory_buffer &formatted) override
{ {
file_helper_.write(formatted); file_helper_.write(formatted);
if (force_flush_)
{
file_helper_.flush();
}
} }
void flush_() override void flush_() override
...@@ -49,11 +39,10 @@ protected: ...@@ -49,11 +39,10 @@ protected:
private: private:
details::file_helper file_helper_; details::file_helper file_helper_;
bool force_flush_;
}; };
using simple_file_sink_mt = simple_file_sink<std::mutex>; using basic_file_sink_mt = basic_file_sink<std::mutex>;
using simple_file_sink_st = simple_file_sink<details::null_mutex>; using basic_file_sink_st = basic_file_sink<details::null_mutex>;
} // namespace sinks } // namespace sinks
...@@ -63,13 +52,13 @@ using simple_file_sink_st = simple_file_sink<details::null_mutex>; ...@@ -63,13 +52,13 @@ using simple_file_sink_st = simple_file_sink<details::null_mutex>;
template<typename Factory = default_factory> template<typename Factory = default_factory>
inline std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false) inline std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false)
{ {
return Factory::template create<sinks::simple_file_sink_mt>(logger_name, filename, truncate); return Factory::template create<sinks::basic_file_sink_mt>(logger_name, filename, truncate);
} }
template<typename Factory = default_factory> template<typename Factory = default_factory>
inline std::shared_ptr<logger> basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false) inline std::shared_ptr<logger> basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false)
{ {
return Factory::template create<sinks::simple_file_sink_st>(logger_name, filename, truncate); return Factory::template create<sinks::basic_file_sink_st>(logger_name, filename, truncate);
} }
} // namespace spdlog } // namespace spdlog
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include "spdlog/details/log_msg.h" #include "spdlog/details/log_msg.h"
#include "spdlog/details/null_mutex.h" #include "spdlog/details/null_mutex.h"
#include "spdlog/sink/base_sink.h"
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
...@@ -18,22 +17,18 @@ ...@@ -18,22 +17,18 @@
namespace spdlog { namespace spdlog {
namespace sinks { namespace sinks {
template<class Mutex>
class dist_sink : public base_sink<Mutex> template<typename Mutex>
class dist_sink : public sink
{ {
public: public:
explicit dist_sink() dist_sink() = default;
: sinks_()
{
}
dist_sink(const dist_sink &) = delete; dist_sink(const dist_sink &) = delete;
dist_sink &operator=(const dist_sink &) = delete; dist_sink &operator=(const dist_sink &) = delete;
protected: void log(const details::log_msg &msg) SPDLOG_FINAL override
std::vector<std::shared_ptr<sink>> sinks_;
void sink_it_(const details::log_msg &msg) override
{ {
std::lock_guard<Mutex> lock(mutex_);
for (auto &sink : sinks_) for (auto &sink : sinks_)
{ {
if (sink->should_log(msg.level)) if (sink->should_log(msg.level))
...@@ -43,24 +38,28 @@ protected: ...@@ -43,24 +38,28 @@ protected:
} }
} }
void flush_() override void flush() SPDLOG_FINAL override
{ {
std::lock_guard<Mutex> lock(mutex_);
for (auto &sink : sinks_) for (auto &sink : sinks_)
sink->flush(); sink->flush();
} }
public:
void add_sink(std::shared_ptr<sink> sink) void add_sink(std::shared_ptr<sink> sink)
{ {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_); std::lock_guard<Mutex> lock(mutex_);
sinks_.push_back(sink); sinks_.push_back(sink);
} }
void remove_sink(std::shared_ptr<sink> sink) void remove_sink(std::shared_ptr<sink> sink)
{ {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_); std::lock_guard<Mutex> lock(mutex_);
sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink), sinks_.end()); sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink), sinks_.end());
} }
private:
Mutex mutex_;
std::vector<std::shared_ptr<sink>> sinks_;
}; };
using dist_sink_mt = dist_sink<std::mutex>; using dist_sink_mt = dist_sink<std::mutex>;
......
...@@ -27,9 +27,9 @@ public: ...@@ -27,9 +27,9 @@ public:
explicit msvc_sink() {} explicit msvc_sink() {}
protected: protected:
void sink_it_(const details::log_msg &msg) override void sink_it_(const details::log_msg &, const fmt::memory_buffer &formatted) override
{ {
OutputDebugStringA(msg.formatted.c_str()); OutputDebugStringA(fmt::to_string(formatted).c_str());
} }
void flush_() override {} void flush_() override {}
...@@ -38,6 +38,9 @@ protected: ...@@ -38,6 +38,9 @@ protected:
using msvc_sink_mt = msvc_sink<std::mutex>; using msvc_sink_mt = msvc_sink<std::mutex>;
using msvc_sink_st = msvc_sink<details::null_mutex>; using msvc_sink_st = msvc_sink<details::null_mutex>;
using windebug_sink_mt = msvc_sink_mt;
using windebug_sink_st = msvc_sink_st;
} // namespace sinks } // namespace sinks
} // namespace spdlog } // namespace spdlog
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#pragma once #pragma once
#include "spdlog/details/log_msg.h" #include "spdlog/details/log_msg.h"
#include "spdlog/details/pattern_formatter.h"
#include "spdlog/formatter.h" #include "spdlog/formatter.h"
namespace spdlog { namespace spdlog {
...@@ -19,17 +20,6 @@ public: ...@@ -19,17 +20,6 @@ public:
{ {
} }
explicit sink(const std::string &formatter_pattern)
: formatter_(std::unique_ptr<spdlog::formatter>(new pattern_formatter(formatter_pattern)))
{
}
// sink with custom formatter
explicit sink(std::unique_ptr<spdlog::formatter> sink_formatter)
: formatter_(std::move(sink_formatter))
{
}
virtual ~sink() = default; virtual ~sink() = default;
virtual void log(const details::log_msg &msg) = 0; virtual void log(const details::log_msg &msg) = 0;
...@@ -39,10 +29,12 @@ public: ...@@ -39,10 +29,12 @@ public:
{ {
return msg_level >= level_.load(std::memory_order_relaxed); return msg_level >= level_.load(std::memory_order_relaxed);
} }
void set_level(level::level_enum log_level) void set_level(level::level_enum log_level)
{ {
level_.store(log_level); level_.store(log_level);
} }
level::level_enum level() const level::level_enum level() const
{ {
return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed)); return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed));
...@@ -58,11 +50,6 @@ public: ...@@ -58,11 +50,6 @@ public:
formatter_ = std::move(sink_formatter); formatter_ = std::move(sink_formatter);
} }
spdlog::formatter *formatter()
{
return formatter_.get();
}
protected: protected:
level_t level_{level::trace}; level_t level_{level::trace};
std::unique_ptr<spdlog::formatter> formatter_; std::unique_ptr<spdlog::formatter> formatter_;
......
...@@ -5,26 +5,27 @@ ...@@ -5,26 +5,27 @@
#pragma once #pragma once
#include "spdlog/details/console_globals.h"
#include "spdlog/details/null_mutex.h" #include "spdlog/details/null_mutex.h"
#include "spdlog/details/traits.h"
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include <cstdio> #include <cstdio>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <spdlog/details/console_globals.h>
namespace spdlog { namespace spdlog {
namespace sinks { namespace sinks {
template<class StdoutTrait, class ConsoleMutexTrait> template<class TargetStream, class ConsoleMutex>
class stdout_sink : public sink class stdout_sink : public sink
{ {
public: public:
using mutex_t = typename ConsoleMutexTrait::mutex_t; using mutex_t = typename ConsoleMutex::mutex_t;
stdout_sink() stdout_sink()
: mutex_(ConsoleMutexTrait::console_mutex()) : mutex_(ConsoleMutex::console_mutex())
, file_(StdoutTrait::stream()) , file_(TargetStream::stream())
{ {
} }
~stdout_sink() = default; ~stdout_sink() = default;
...@@ -35,14 +36,16 @@ public: ...@@ -35,14 +36,16 @@ public:
void log(const details::log_msg &msg) override void log(const details::log_msg &msg) override
{ {
std::lock_guard<mutex_t> lock(mutex_); std::lock_guard<mutex_t> lock(mutex_);
fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), file_); fmt::memory_buffer formatted;
fflush(StdoutTrait::stream()); formatter_->format(msg, formatted);
fwrite(formatted.data(), sizeof(char), formatted.size(), file_);
fflush(TargetStream::stream());
} }
void flush() override void flush() override
{ {
std::lock_guard<mutex_t> lock(mutex_); std::lock_guard<mutex_t> lock(mutex_);
fflush(StdoutTrait::stream()); fflush(TargetStream::stream());
} }
private: private:
...@@ -50,10 +53,11 @@ private: ...@@ -50,10 +53,11 @@ private:
FILE *file_; FILE *file_;
}; };
using stdout_sink_mt = stdout_sink<details::console_stdout_trait, details::console_mutex_trait>; using stdout_sink_mt = stdout_sink<details::console_stdout_stream, details::console_global_mutex>;
using stdout_sink_st = stdout_sink<details::console_stdout_trait, details::console_null_mutex_trait>; using stdout_sink_st = stdout_sink<details::console_stdout_stream, details::console_global_nullmutex>;
using stderr_sink_mt = stdout_sink<details::console_stderr_trait, details::console_mutex_trait>;
using stderr_sink_st = stdout_sink<details::console_stderr_trait, details::console_null_mutex_trait>; using stderr_sink_mt = stdout_sink<details::console_stderr_stream, details::console_global_mutex>;
using stderr_sink_st = stdout_sink<details::console_stderr_stream, details::console_global_nullmutex>;
} // namespace sinks } // namespace sinks
......
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
#include "../fmt/fmt.h" #include "../fmt/fmt.h"
#include "spdlog/common.h" #include "spdlog/common.h"
#include "spdlog/details/console_globals.h"
#include "spdlog/details/null_mutex.h" #include "spdlog/details/null_mutex.h"
#include "spdlog/details/traits.h"
#include "spdlog/sinks/sink.h" #include "spdlog/sinks/sink.h"
#include <memory> #include <memory>
...@@ -22,7 +22,7 @@ namespace sinks { ...@@ -22,7 +22,7 @@ namespace sinks {
/* /*
* Windows color console sink. Uses WriteConsoleA to write to the console with colors * Windows color console sink. Uses WriteConsoleA to write to the console with colors
*/ */
template<class HandleTrait, class ConsoleMutexTrait> template<class OutHandle, class ConsoleMutex>
class wincolor_sink : public sink class wincolor_sink : public sink
{ {
public: public:
...@@ -34,8 +34,8 @@ public: ...@@ -34,8 +34,8 @@ public:
const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN; const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN;
wincolor_sink() wincolor_sink()
: out_handle_(HandleTrait::handle()) : out_handle_(OutHandle::handle())
, mutex_(ConsoleMutexTrait::console_mutex()) , mutex_(ConsoleMutex::console_mutex())
{ {
colors_[level::trace] = WHITE; colors_[level::trace] = WHITE;
colors_[level::debug] = CYAN; colors_[level::debug] = CYAN;
...@@ -90,7 +90,7 @@ public: ...@@ -90,7 +90,7 @@ public:
} }
private: private:
using mutex_t = typename ConsoleMutexTrait::mutex_t; using mutex_t = typename ConsoleMutex::mutex_t;
// set color and return the orig console attributes (for resetting later) // set color and return the orig console attributes (for resetting later)
WORD set_console_attribs(WORD attribs) WORD set_console_attribs(WORD attribs)
{ {
...@@ -116,11 +116,11 @@ private: ...@@ -116,11 +116,11 @@ private:
std::unordered_map<level::level_enum, WORD, level::level_hasher> colors_; std::unordered_map<level::level_enum, WORD, level::level_hasher> colors_;
}; };
using wincolor_stdout_sink_mt = wincolor_sink<details::console_stdout_trait, details::console_mutex_trait>; using wincolor_stdout_sink_mt = wincolor_sink<details::console_stdout_stream, details::console_global_mutex>;
using wincolor_stdout_sink_st = wincolor_sink<details::console_stdout_trait, details::console_null_mutex_trait>; using wincolor_stdout_sink_st = wincolor_sink<details::console_stdout_stream, details::console_global_nullmutex>;
using wincolor_stderr_sink_mt = wincolor_sink<details::console_stderr_trait, details::console_mutex_trait>; using wincolor_stderr_sink_mt = wincolor_sink<details::console_stderr_stream, details::console_global_mutex>;
using wincolor_stderr_sink_st = wincolor_sink<details::console_stderr_trait, details::console_null_mutex_trait>; using wincolor_stderr_sink_st = wincolor_sink<details::console_stderr_stream, details::console_global_nullmutex>;
} // namespace sinks } // namespace sinks
} // namespace spdlog } // namespace spdlog
//
// Copyright(c) 2017 Alexander Dalshov.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
#if defined(_WIN32)
#include "spdlog/sinks/msvc_sink.h"
namespace spdlog {
namespace sinks {
/*
* 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 sinks
} // namespace spdlog
#endif
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
namespace spdlog { namespace spdlog {
// Default logger factory- creates synchronous loggers // Default logger factory- creates synchronous loggers
struct create_synchronous struct synchronous_factory
{ {
template<typename Sink, typename... SinkArgs> template<typename Sink, typename... SinkArgs>
...@@ -32,7 +32,7 @@ struct create_synchronous ...@@ -32,7 +32,7 @@ struct create_synchronous
} }
}; };
using default_factory = create_synchronous; using default_factory = synchronous_factory;
// Create and register a logger with a templated sink type // Create and register a logger with a templated sink type
// The logger's level, formatter and flush level will be set according the global settings. // The logger's level, formatter and flush level will be set according the global settings.
...@@ -57,9 +57,9 @@ inline std::shared_ptr<logger> get(const std::string &name) ...@@ -57,9 +57,9 @@ inline std::shared_ptr<logger> get(const std::string &name)
// Set global formatting // Set global formatting
// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v"); // example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v");
// //
inline void set_pattern(const std::string &format_string) inline void set_pattern(const std::string &format_string, pattern_time_type time_type = pattern_time_type::local)
{ {
details::registry::instance().set_pattern(format_string); details::registry::instance().set_pattern(format_string, time_type);
} }
// //
......
...@@ -24,7 +24,7 @@ TEST_CASE("default_error_handler", "[errors]]") ...@@ -24,7 +24,7 @@ TEST_CASE("default_error_handler", "[errors]]")
prepare_logdir(); prepare_logdir();
std::string filename = "logs/simple_log.txt"; std::string filename = "logs/simple_log.txt";
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("test-error", filename, true); auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("test-error", filename, true);
logger->set_pattern("%v"); logger->set_pattern("%v");
logger->info("Test message {} {}", 1); logger->info("Test message {} {}", 1);
logger->info("Test message {}", 2); logger->info("Test message {}", 2);
...@@ -41,7 +41,7 @@ TEST_CASE("custom_error_handler", "[errors]]") ...@@ -41,7 +41,7 @@ TEST_CASE("custom_error_handler", "[errors]]")
{ {
prepare_logdir(); prepare_logdir();
std::string filename = "logs/simple_log.txt"; std::string filename = "logs/simple_log.txt";
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename, true); auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
logger->flush_on(spdlog::level::info); logger->flush_on(spdlog::level::info);
logger->set_error_handler([=](const std::string &) { throw custom_ex(); }); logger->set_error_handler([=](const std::string &) { throw custom_ex(); });
logger->info("Good message #1"); logger->info("Good message #1");
...@@ -75,7 +75,7 @@ TEST_CASE("async_error_handler", "[errors]]") ...@@ -75,7 +75,7 @@ TEST_CASE("async_error_handler", "[errors]]")
std::string filename = "logs/simple_async_log.txt"; std::string filename = "logs/simple_async_log.txt";
{ {
spdlog::init_thread_pool(128, 1); spdlog::init_thread_pool(128, 1);
auto logger = spdlog::create_async_logger<spdlog::sinks::simple_file_sink_mt>("logger", filename, true); auto logger = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
logger->set_error_handler([=](const std::string &) { logger->set_error_handler([=](const std::string &) {
std::ofstream ofs("logs/custom_err.txt"); std::ofstream ofs("logs/custom_err.txt");
if (!ofs) if (!ofs)
...@@ -99,7 +99,7 @@ TEST_CASE("async_error_handler2", "[errors]]") ...@@ -99,7 +99,7 @@ TEST_CASE("async_error_handler2", "[errors]]")
std::string err_msg("This is async handler error message"); std::string err_msg("This is async handler error message");
{ {
spdlog::init_thread_pool(128, 1); spdlog::init_thread_pool(128, 1);
auto logger = spdlog::create_async_logger<failing_sink>("failed_logger"); auto logger = spdlog::create_async<failing_sink>("failed_logger");
logger->set_error_handler([=](const std::string &) { logger->set_error_handler([=](const std::string &) {
std::ofstream ofs("logs/custom_err2.txt"); std::ofstream ofs("logs/custom_err2.txt");
if (!ofs) if (!ofs)
......
...@@ -8,7 +8,7 @@ TEST_CASE("simple_file_logger", "[simple_logger]]") ...@@ -8,7 +8,7 @@ TEST_CASE("simple_file_logger", "[simple_logger]]")
prepare_logdir(); prepare_logdir();
std::string filename = "logs/simple_log"; std::string filename = "logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename); auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v"); logger->set_pattern("%v");
logger->info("Test message {}", 1); logger->info("Test message {}", 1);
...@@ -24,7 +24,7 @@ TEST_CASE("flush_on", "[flush_on]]") ...@@ -24,7 +24,7 @@ TEST_CASE("flush_on", "[flush_on]]")
prepare_logdir(); prepare_logdir();
std::string filename = "logs/simple_log"; std::string filename = "logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename); auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v"); logger->set_pattern("%v");
logger->set_level(spdlog::level::trace); logger->set_level(spdlog::level::trace);
logger->flush_on(spdlog::level::info); logger->flush_on(spdlog::level::info);
......
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
#define SPDLOG_DEBUG_ON #define SPDLOG_DEBUG_ON
#include "spdlog/async.h" #include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h" #include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h" #include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/ostream_sink.h" #include "spdlog/sinks/ostream_sink.h"
#include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/simple_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h" #include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include "includes.h" #include "includes.h"
#include "spdlog/async.h" #include "spdlog/async.h"
#include "spdlog/sinks/simple_file_sink.h" #include "spdlog/sinks/basic_file_sink.h"
#include "test_sink.h" #include "test_sink.h"
TEST_CASE("basic async test ", "[async]") TEST_CASE("basic async test ", "[async]")
...@@ -11,7 +11,7 @@ TEST_CASE("basic async test ", "[async]") ...@@ -11,7 +11,7 @@ TEST_CASE("basic async test ", "[async]")
size_t messages = 256; size_t messages = 256;
{ {
auto tp = std::make_shared<details::thread_pool>(queue_size, 1); auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block_retry); auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block);
for (size_t i = 0; i < messages; i++) for (size_t i = 0; i < messages; i++)
{ {
logger->info("Hello message #{}", i); logger->info("Hello message #{}", i);
...@@ -30,7 +30,7 @@ TEST_CASE("discard policy ", "[async]") ...@@ -30,7 +30,7 @@ TEST_CASE("discard policy ", "[async]")
size_t messages = 1024; size_t messages = 1024;
{ {
auto tp = std::make_shared<details::thread_pool>(queue_size, 1); auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::overrun_oldeset); auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::overrun_oldest);
for (size_t i = 0; i < messages; i++) for (size_t i = 0; i < messages; i++)
{ {
logger->info("Hello message #{}", i); logger->info("Hello message #{}", i);
...@@ -48,7 +48,7 @@ TEST_CASE("flush", "[async]") ...@@ -48,7 +48,7 @@ TEST_CASE("flush", "[async]")
size_t messages = 256; size_t messages = 256;
{ {
auto tp = std::make_shared<details::thread_pool>(queue_size, 1); auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block_retry); auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block);
for (size_t i = 0; i < messages; i++) for (size_t i = 0; i < messages; i++)
{ {
logger->info("Hello message #{}", i); logger->info("Hello message #{}", i);
...@@ -69,7 +69,7 @@ TEST_CASE("tp->wait_empty() ", "[async]") ...@@ -69,7 +69,7 @@ TEST_CASE("tp->wait_empty() ", "[async]")
size_t messages = 100; size_t messages = 100;
auto tp = std::make_shared<details::thread_pool>(messages, 2); auto tp = std::make_shared<details::thread_pool>(messages, 2);
auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block_retry); auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block);
for (size_t i = 0; i < messages; i++) for (size_t i = 0; i < messages; i++)
{ {
logger->info("Hello message #{}", i); logger->info("Hello message #{}", i);
...@@ -90,7 +90,7 @@ TEST_CASE("multi threads", "[async]") ...@@ -90,7 +90,7 @@ TEST_CASE("multi threads", "[async]")
size_t n_threads = 10; size_t n_threads = 10;
{ {
auto tp = std::make_shared<details::thread_pool>(queue_size, 1); auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block_retry); auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::block);
std::vector<std::thread> threads; std::vector<std::thread> threads;
for (size_t i = 0; i < n_threads; i++) for (size_t i = 0; i < n_threads; i++)
...@@ -121,7 +121,7 @@ TEST_CASE("to_file", "[async]") ...@@ -121,7 +121,7 @@ TEST_CASE("to_file", "[async]")
size_t tp_threads = 1; size_t tp_threads = 1;
std::string filename = "logs/async_test.log"; std::string filename = "logs/async_test.log";
{ {
auto file_sink = std::make_shared<spdlog::sinks::simple_file_sink_mt>(filename, true); auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads); auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
auto logger = std::make_shared<spdlog::async_logger>("as", std::move(file_sink), std::move(tp)); auto logger = std::make_shared<spdlog::async_logger>("as", std::move(file_sink), std::move(tp));
...@@ -143,7 +143,7 @@ TEST_CASE("to_file multi-workers", "[async]") ...@@ -143,7 +143,7 @@ TEST_CASE("to_file multi-workers", "[async]")
size_t tp_threads = 10; size_t tp_threads = 10;
std::string filename = "logs/async_test.log"; std::string filename = "logs/async_test.log";
{ {
auto file_sink = std::make_shared<spdlog::sinks::simple_file_sink_mt>(filename, true); auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads); auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
auto logger = std::make_shared<spdlog::async_logger>("as", std::move(file_sink), std::move(tp)); auto logger = std::make_shared<spdlog::async_logger>("as", std::move(file_sink), std::move(tp));
......
...@@ -9,12 +9,11 @@ TEST_CASE("debug and trace w/o format string", "[macros]]") ...@@ -9,12 +9,11 @@ TEST_CASE("debug and trace w/o format string", "[macros]]")
prepare_logdir(); prepare_logdir();
std::string filename = "logs/simple_log"; std::string filename = "logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename); auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v"); logger->set_pattern("%v");
logger->set_level(spdlog::level::trace); logger->set_level(spdlog::level::trace);
SPDLOG_TRACE(logger, "Test message 1"); 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(); logger->flush();
...@@ -27,7 +26,7 @@ TEST_CASE("debug and trace with format strings", "[macros]]") ...@@ -27,7 +26,7 @@ TEST_CASE("debug and trace with format strings", "[macros]]")
prepare_logdir(); prepare_logdir();
std::string filename = "logs/simple_log"; std::string filename = "logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename); auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v"); logger->set_pattern("%v");
logger->set_level(spdlog::level::trace); logger->set_level(spdlog::level::trace);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment