Commit 0d263598 authored by gabime's avatar gabime

astyle

parent 0f889969
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#include <thread> #include <thread>
#include <vector> #include <vector>
#include <atomic> #include <atomic>
#include <iostream> #include <iostream>
#include <chrono> #include <chrono>
#include <cstdlib> #include <cstdlib>
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
using namespace std; using namespace std;
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
using namespace std::chrono; using namespace std::chrono;
using clock=steady_clock; using clock=steady_clock;
namespace spd = spdlog; namespace spd = spdlog;
int thread_count = 10; int thread_count = 10;
if(argc > 1) if(argc > 1)
thread_count = ::atoi(argv[1]); thread_count = ::atoi(argv[1]);
int howmany = 1000000; int howmany = 1000000;
spd::set_async_mode(1048576); spd::set_async_mode(1048576);
auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "logs/spd-bench-async.txt", false); auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "logs/spd-bench-async.txt", false);
logger->set_pattern("[%Y-%b-%d %T.%e]: %v"); logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
std::atomic<int > msg_counter {0}; std::atomic<int > msg_counter {0};
vector<thread> threads; vector<thread> threads;
auto start = clock::now(); auto start = clock::now();
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() threads.push_back(std::thread([&]()
{ {
while (true) while (true)
{ {
int counter = ++msg_counter; int counter = ++msg_counter;
if (counter > howmany) break; if (counter > howmany) break;
logger->info() << "spdlog message #" << counter << ": This is some text for your pleasure"; logger->info() << "spdlog message #" << counter << ": This is some text for your pleasure";
} }
})); }));
} }
for(auto &t:threads) for(auto &t:threads)
{ {
t.join(); t.join();
}; };
duration<float> delta = clock::now() - start; duration<float> delta = clock::now() - start;
float deltaf = delta.count(); float deltaf = delta.count();
auto rate = howmany/deltaf; auto rate = howmany/deltaf;
cout << "Total: " << howmany << std::endl; cout << "Total: " << howmany << std::endl;
cout << "Threads: " << thread_count << std::endl; cout << "Threads: " << thread_count << std::endl;
std::cout << "Delta = " << deltaf << " seconds" << std::endl; std::cout << "Delta = " << deltaf << " seconds" << std::endl;
std::cout << "Rate = " << rate << "/sec" << std::endl; std::cout << "Rate = " << rate << "/sec" << std::endl;
} }
#include <thread> #include <thread>
#include <vector> #include <vector>
#include <atomic> #include <atomic>
#include <cstdlib> #include <cstdlib>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <zf_log.c> #include <zf_log.c>
const char g_path[] = "logs/zf_log.txt"; const char g_path[] = "logs/zf_log.txt";
int g_fd; int g_fd;
static void output_callback(zf_log_message *msg) static void output_callback(zf_log_message *msg)
{ {
*msg->p = '\n'; *msg->p = '\n';
write(g_fd, msg->buf, msg->p - msg->buf + 1); write(g_fd, msg->buf, msg->p - msg->buf + 1);
} }
using namespace std; using namespace std;
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
g_fd = open(g_path, O_APPEND|O_CREAT|O_WRONLY); g_fd = open(g_path, O_APPEND|O_CREAT|O_WRONLY);
if (0 > g_fd) if (0 > g_fd)
{ {
ZF_LOGE_AUX(ZF_LOG_STDERR, "Failed to open log file: %s", g_path); ZF_LOGE_AUX(ZF_LOG_STDERR, "Failed to open log file: %s", g_path);
return -1; return -1;
} }
zf_log_set_output_callback(ZF_LOG_PUT_STD, output_callback); zf_log_set_output_callback(ZF_LOG_PUT_STD, output_callback);
int thread_count = 10; int thread_count = 10;
if(argc > 1) if(argc > 1)
thread_count = std::atoi(argv[1]); thread_count = std::atoi(argv[1]);
int howmany = 1000000; int howmany = 1000000;
std::atomic<int > msg_counter {0}; std::atomic<int > msg_counter {0};
vector<thread> threads; vector<thread> threads;
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() threads.push_back(std::thread([&]()
{ {
while (true) while (true)
{ {
int counter = ++msg_counter; int counter = ++msg_counter;
if (counter > howmany) break; if (counter > howmany) break;
ZF_LOGI("zf_log message #%i: This is some text for your pleasure", counter); ZF_LOGI("zf_log message #%i: This is some text for your pleasure", counter);
} }
})); }));
} }
for (auto &t:threads) for (auto &t:threads)
{ {
t.join(); t.join();
}; };
close(g_fd); close(g_fd);
return 0; return 0;
} }
#include <stdio.h> #include <stdio.h>
#include <zf_log.c> #include <zf_log.c>
const char g_path[] = "logs/zf_log.txt"; const char g_path[] = "logs/zf_log.txt";
static FILE *g_f; static FILE *g_f;
static void output_callback(zf_log_message *msg) static void output_callback(zf_log_message *msg)
{ {
*msg->p = '\n'; *msg->p = '\n';
fwrite(msg->buf, msg->p - msg->buf + 1, 1, g_f); fwrite(msg->buf, msg->p - msg->buf + 1, 1, g_f);
} }
int main(int, char* []) int main(int, char* [])
{ {
g_f = fopen(g_path, "wb"); g_f = fopen(g_path, "wb");
if (!g_f) if (!g_f)
{ {
ZF_LOGE_AUX(ZF_LOG_STDERR, "Failed to open log file: %s", g_path); ZF_LOGE_AUX(ZF_LOG_STDERR, "Failed to open log file: %s", g_path);
return -1; return -1;
} }
zf_log_set_output_callback(ZF_LOG_PUT_STD, output_callback); zf_log_set_output_callback(ZF_LOG_PUT_STD, output_callback);
const int howmany = 1000000; const int howmany = 1000000;
for(int i = 0 ; i < howmany; ++i) for(int i = 0 ; i < howmany; ++i)
ZF_LOGI("zf_log message #%i: This is some text for your pleasure", i); ZF_LOGI("zf_log message #%i: This is some text for your pleasure", i);
fclose(g_f); fclose(g_f);
return 0; return 0;
} }
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
// //
// spdlog usage example // spdlog usage example
// //
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include <cstdlib> // EXIT_FAILURE #include <cstdlib> // EXIT_FAILURE
#include <iostream> #include <iostream>
#include <memory> #include <memory>
void async_example(); void async_example();
void syslog_example(); void syslog_example();
namespace spd = spdlog; namespace spd = spdlog;
int main(int, char*[]) int main(int, char*[])
{ {
try try
{ {
// Multithreaded color console // Multithreaded color console
auto console = spd::stdout_logger_mt("console", true); auto console = spd::stdout_logger_mt("console", true);
console->info("Welcome to spdlog!"); console->info("Welcome to spdlog!");
console->info("An info message example {}..", 1); console->info("An info message example {}..", 1);
console->info() << "Streams are supported too " << 1; console->info() << "Streams are supported too " << 1;
// Formatting examples // Formatting examples
console->info("Easy padding in numbers like {:08d}", 12); console->info("Easy padding in numbers like {:08d}", 12);
console->info("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); console->info("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
console->info("Support for floats {:03.2f}", 1.23456); console->info("Support for floats {:03.2f}", 1.23456);
console->info("Positional args are {1} {0}..", "too", "supported"); console->info("Positional args are {1} {0}..", "too", "supported");
console->info("{:<30}", "left aligned"); console->info("{:<30}", "left aligned");
console->info("{:>30}", "right aligned"); console->info("{:>30}", "right aligned");
console->info("{:^30}", "centered"); console->info("{:^30}", "centered");
spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function"); spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
// Runtime log levels // Runtime log levels
spd::set_level(spd::level::info); //Set global log level to info spd::set_level(spd::level::info); //Set global log level to info
console->debug("This message shold not be displayed!"); console->debug("This message shold not be displayed!");
console->set_level(spd::level::debug); // Set specific logger's log level console->set_level(spd::level::debug); // Set specific logger's log level
console->debug("This message shold be displayed.."); console->debug("This message shold be displayed..");
// Create a file rotating logger with 5mb size max and 3 rotated files // Create a file rotating logger with 5mb size max and 3 rotated files
auto file_logger = spd::rotating_logger_mt("file_logger", "logs/mylogfile", 1048576 * 5, 3); auto file_logger = spd::rotating_logger_mt("file_logger", "logs/mylogfile", 1048576 * 5, 3);
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
file_logger->info("{} * {} equals {:>10}", i, i, i*i); file_logger->info("{} * {} equals {:>10}", i, i, i*i);
// Create a daily logger - a new file is created every day on 2:30am // Create a daily logger - a new file is created every day on 2:30am
auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily", 2, 30); auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily", 2, 30);
// Customize msg format for all messages // Customize msg format for all messages
spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***"); spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
file_logger->info("This is another message with custom format"); file_logger->info("This is another message with custom format");
// Compile time debug or trace macros. // Compile time debug or trace macros.
// Enabled #ifdef SPDLOG_DEBUG_ON or #ifdef SPDLOG_TRACE_ON // Enabled #ifdef SPDLOG_DEBUG_ON or #ifdef SPDLOG_TRACE_ON
SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23); SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23); SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
// Asynchronous logging is very fast.. // Asynchronous logging is very fast..
// Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous.. // Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
async_example(); async_example();
// syslog example. linux/osx only.. // syslog example. linux/osx only..
syslog_example(); syslog_example();
// Release and close all loggers // Release and close all loggers
spdlog::drop_all(); spdlog::drop_all();
} }
catch (const spd::spdlog_ex& ex) catch (const spd::spdlog_ex& ex)
{ {
std::cout << "Log failed: " << ex.what() << std::endl; std::cout << "Log failed: " << ex.what() << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void async_example() void async_example()
{ {
size_t q_size = 4096; //queue size must be power of 2 size_t q_size = 4096; //queue size must be power of 2
spdlog::set_async_mode(q_size); spdlog::set_async_mode(q_size);
auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt"); auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
for (int i = 0; i < 100; ++i) for (int i = 0; i < 100; ++i)
async_file->info("Async message #{}", i); async_file->info("Async message #{}", i);
} }
//syslog example (linux/osx only) //syslog example (linux/osx only)
void syslog_example() void syslog_example()
{ {
#if defined (__linux__) || defined(__APPLE__) #if defined (__linux__) || defined(__APPLE__)
std::string ident = "spdlog-example"; std::string ident = "spdlog-example";
auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID); auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID);
syslog_logger->warn("This is warning that will end up in syslog. This is Linux only!"); syslog_logger->warn("This is warning that will end up in syslog. This is Linux only!");
#endif #endif
} }
// Example of user defined class with operator<< // Example of user defined class with operator<<
class some_class {}; class some_class {};
std::ostream& operator<<(std::ostream& os, const some_class&) std::ostream& operator<<(std::ostream& os, const some_class&)
{ {
return os << "some_class"; return os << "some_class";
} }
void custom_class_example() void custom_class_example()
{ {
some_class c; some_class c;
spdlog::get("console")->info("custom class with operator<<: {}..", c); spdlog::get("console")->info("custom class with operator<<: {}..", c);
spdlog::get("console")->info() << "custom class with operator<<: " << c << ".."; spdlog::get("console")->info() << "custom class with operator<<: " << c << "..";
} }
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
// Very fast asynchronous logger (millions of logs per second on an average desktop) // Very fast asynchronous logger (millions of logs per second on an average desktop)
// Uses pre allocated lockfree queue for maximum throughput even under large number of threads. // Uses pre allocated lockfree queue for maximum throughput even under large number of threads.
// Creates a single back thread to pop messages from the queue and log them. // Creates a single back thread to pop messages from the queue and log them.
// //
// Upon each log write the logger: // Upon each log write the logger:
// 1. Checks if its log level is enough to log the message // 1. Checks if its log level is enough to log the message
// 2. Push a new copy of the message to a queue (or block the caller until space is available in the queue) // 2. Push a new copy of the message to a queue (or block the caller until space is available in the queue)
// 3. will throw spdlog_ex upon log exceptions // 3. will throw spdlog_ex upon log exceptions
// Upong destruction, logs all remaining messages in the queue before destructing.. // Upong destruction, logs all remaining messages in the queue before destructing..
#include <spdlog/common.h> #include <spdlog/common.h>
#include <spdlog/logger.h> #include <spdlog/logger.h>
#include <chrono> #include <chrono>
#include <functional> #include <functional>
#include <string> #include <string>
#include <memory> #include <memory>
namespace spdlog namespace spdlog
{ {
namespace details namespace details
{ {
class async_log_helper; class async_log_helper;
} }
class async_logger :public logger class async_logger :public logger
{ {
public: public:
template<class It> template<class It>
async_logger(const std::string& name, async_logger(const std::string& name,
const It& begin, const It& begin,
const It& end, const It& end,
size_t queue_size, size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()>& worker_warmup_cb = nullptr, const std::function<void()>& worker_warmup_cb = nullptr,
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero()); const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
async_logger(const std::string& logger_name, async_logger(const std::string& logger_name,
sinks_init_list sinks, sinks_init_list sinks,
size_t queue_size, size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()>& worker_warmup_cb = nullptr, const std::function<void()>& worker_warmup_cb = nullptr,
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero()); const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
async_logger(const std::string& logger_name, async_logger(const std::string& logger_name,
sink_ptr single_sink, sink_ptr single_sink,
size_t queue_size, size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()>& worker_warmup_cb = nullptr, const std::function<void()>& worker_warmup_cb = nullptr,
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero()); const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
void flush() override; void flush() override;
protected: protected:
void _log_msg(details::log_msg& msg) override; void _log_msg(details::log_msg& msg) override;
void _set_formatter(spdlog::formatter_ptr msg_formatter) override; void _set_formatter(spdlog::formatter_ptr msg_formatter) override;
void _set_pattern(const std::string& pattern) override; void _set_pattern(const std::string& pattern) override;
private: private:
std::unique_ptr<details::async_log_helper> _async_log_helper; std::unique_ptr<details::async_log_helper> _async_log_helper;
}; };
} }
#include <spdlog/details/async_logger_impl.h> #include <spdlog/details/async_logger_impl.h>
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
#include <string> #include <string>
#include <initializer_list> #include <initializer_list>
#include <chrono> #include <chrono>
#include <memory> #include <memory>
#include <atomic> #include <atomic>
#include <exception> #include <exception>
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
#include <codecvt> #include <codecvt>
#include <locale> #include <locale>
#endif #endif
#include <spdlog/details/null_mutex.h> #include <spdlog/details/null_mutex.h>
//visual studio does not support noexcept yet //visual studio does not support noexcept yet
#ifndef _MSC_VER #ifndef _MSC_VER
#define SPDLOG_NOEXCEPT noexcept #define SPDLOG_NOEXCEPT noexcept
#else #else
#define SPDLOG_NOEXCEPT throw() #define SPDLOG_NOEXCEPT throw()
#endif #endif
namespace spdlog namespace spdlog
{ {
class formatter; class formatter;
namespace sinks namespace sinks
{ {
class sink; class sink;
} }
// Common types across the lib // Common types across the lib
using log_clock = std::chrono::system_clock; 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
using level_t = std::atomic_int; using level_t = std::atomic_int;
#endif #endif
//Log level enum //Log level enum
namespace level namespace level
{ {
typedef enum typedef enum
{ {
trace = 0, trace = 0,
debug = 1, debug = 1,
info = 2, info = 2,
notice = 3, notice = 3,
warn = 4, warn = 4,
err = 5, err = 5,
critical = 6, critical = 6,
alert = 7, alert = 7,
emerg = 8, emerg = 8,
off = 9 off = 9
} level_enum; } level_enum;
static const char* level_names[] { "trace", "debug", "info", "notice", "warning", "error", "critical", "alert", "emerg", "off"}; static const char* level_names[] { "trace", "debug", "info", "notice", "warning", "error", "critical", "alert", "emerg", "off"};
static const char* short_level_names[] { "T", "D", "I", "N", "W", "E", "C", "A", "M", "O"}; static const char* short_level_names[] { "T", "D", "I", "N", "W", "E", "C", "A", "M", "O"};
inline const char* to_str(spdlog::level::level_enum l) inline const char* to_str(spdlog::level::level_enum l)
{ {
return level_names[l]; return level_names[l];
} }
inline const char* to_short_str(spdlog::level::level_enum l) inline const char* to_short_str(spdlog::level::level_enum l)
{ {
return short_level_names[l]; return short_level_names[l];
} }
} //level } //level
// //
// Async overflow policy - block by default. // Async overflow policy - block by default.
// //
enum class async_overflow_policy enum class async_overflow_policy
{ {
block_retry, // Block / yield / sleep until message can be enqueued block_retry, // Block / yield / sleep until message can be enqueued
discard_log_msg // Discard the message it enqueue fails discard_log_msg // Discard the message it enqueue fails
}; };
// //
// Log exception // Log exception
// //
class spdlog_ex : public std::exception class spdlog_ex : public std::exception
{ {
public: public:
spdlog_ex(const std::string& msg) :_msg(msg) {} spdlog_ex(const std::string& msg) :_msg(msg) {}
const char* what() const SPDLOG_NOEXCEPT override const char* what() const SPDLOG_NOEXCEPT override
{ {
return _msg.c_str(); return _msg.c_str();
} }
private: private:
std::string _msg; std::string _msg;
}; };
// //
// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined) // wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
// //
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
#define SPDLOG_FILENAME_T(s) L ## s #define SPDLOG_FILENAME_T(s) L ## s
using filename_t = std::wstring; using filename_t = std::wstring;
inline std::string filename_to_str(const filename_t& filename) inline std::string filename_to_str(const filename_t& filename)
{ {
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> c; std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> c;
return c.to_bytes(filename); return c.to_bytes(filename);
} }
#else #else
#define SPDLOG_FILENAME_T(s) s #define SPDLOG_FILENAME_T(s) s
using filename_t = std::string; using filename_t = std::string;
inline std::string filename_to_str(const filename_t& filename) inline std::string filename_to_str(const filename_t& filename)
{ {
return filename; return filename;
} }
#endif #endif
} //spdlog } //spdlog
This diff is collapsed.
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
// Async Logger implementation // Async Logger implementation
// Use an async_sink (queue per logger) to perform the logging in a worker thread // Use an async_sink (queue per logger) to perform the logging in a worker thread
#include <spdlog/details/async_log_helper.h> #include <spdlog/details/async_log_helper.h>
#include <spdlog/async_logger.h> #include <spdlog/async_logger.h>
#include <string> #include <string>
#include <functional> #include <functional>
#include <chrono> #include <chrono>
#include <memory> #include <memory>
template<class It> template<class It>
inline spdlog::async_logger::async_logger(const std::string& logger_name, inline spdlog::async_logger::async_logger(const std::string& logger_name,
const It& begin, const It& begin,
const It& end, const It& end,
size_t queue_size, size_t queue_size,
const async_overflow_policy overflow_policy, const async_overflow_policy overflow_policy,
const std::function<void()>& worker_warmup_cb, const std::function<void()>& worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms) : const std::chrono::milliseconds& flush_interval_ms) :
logger(logger_name, begin, end), logger(logger_name, begin, end),
_async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms)) _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms))
{ {
} }
inline spdlog::async_logger::async_logger(const std::string& logger_name, inline spdlog::async_logger::async_logger(const std::string& logger_name,
sinks_init_list sinks, sinks_init_list sinks,
size_t queue_size, size_t queue_size,
const async_overflow_policy overflow_policy, const async_overflow_policy overflow_policy,
const std::function<void()>& worker_warmup_cb, const std::function<void()>& worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms) : const std::chrono::milliseconds& flush_interval_ms) :
async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {} async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {}
inline spdlog::async_logger::async_logger(const std::string& logger_name, inline spdlog::async_logger::async_logger(const std::string& logger_name,
sink_ptr single_sink, sink_ptr single_sink,
size_t queue_size, size_t queue_size,
const async_overflow_policy overflow_policy, const async_overflow_policy overflow_policy,
const std::function<void()>& worker_warmup_cb, const std::function<void()>& worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms) : const std::chrono::milliseconds& flush_interval_ms) :
async_logger(logger_name, async_logger(logger_name,
{ {
single_sink single_sink
}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {} }, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {}
inline void spdlog::async_logger::flush() inline void spdlog::async_logger::flush()
{ {
_async_log_helper->flush(); _async_log_helper->flush();
} }
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)
{ {
_formatter = msg_formatter; _formatter = msg_formatter;
_async_log_helper->set_formatter(_formatter); _async_log_helper->set_formatter(_formatter);
} }
inline void spdlog::async_logger::_set_pattern(const std::string& pattern) inline void spdlog::async_logger::_set_pattern(const std::string& pattern)
{ {
_formatter = std::make_shared<pattern_formatter>(pattern); _formatter = std::make_shared<pattern_formatter>(pattern);
_async_log_helper->set_formatter(_formatter); _async_log_helper->set_formatter(_formatter);
} }
inline void spdlog::async_logger::_log_msg(details::log_msg& msg) inline void spdlog::async_logger::_log_msg(details::log_msg& msg)
{ {
_async_log_helper->log(msg); _async_log_helper->log(msg);
} }
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
// Helper class for file sink // Helper class for file sink
// When failing to open a file, retry several times(5) with small delay between the tries(10 ms) // When failing to open a file, retry several times(5) with small delay between the tries(10 ms)
// Can be set to auto flush on every line // Can be set to auto flush on every line
// Throw spdlog_ex exception on errors // Throw spdlog_ex exception on errors
#include <spdlog/details/os.h> #include <spdlog/details/os.h>
#include <spdlog/details/log_msg.h> #include <spdlog/details/log_msg.h>
#include <chrono> #include <chrono>
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include <thread> #include <thread>
namespace spdlog namespace spdlog
{ {
namespace details namespace details
{ {
class file_helper class file_helper
{ {
public: public:
const int open_tries = 5; const int open_tries = 5;
const int open_interval = 10; const int open_interval = 10;
explicit file_helper(bool force_flush) : explicit file_helper(bool force_flush) :
_fd(nullptr), _fd(nullptr),
_force_flush(force_flush) _force_flush(force_flush)
{} {}
file_helper(const file_helper&) = delete; file_helper(const file_helper&) = delete;
file_helper& operator=(const file_helper&) = delete; file_helper& operator=(const file_helper&) = delete;
~file_helper() ~file_helper()
{ {
close(); close();
} }
void open(const filename_t& fname, bool truncate = false) void open(const filename_t& fname, bool truncate = false)
{ {
close(); close();
auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
_filename = fname; _filename = fname;
for (int tries = 0; tries < open_tries; ++tries) for (int tries = 0; tries < open_tries; ++tries)
{ {
if (!os::fopen_s(&_fd, fname, mode)) if (!os::fopen_s(&_fd, fname, mode))
return; return;
std::this_thread::sleep_for(std::chrono::milliseconds(open_interval)); std::this_thread::sleep_for(std::chrono::milliseconds(open_interval));
} }
throw spdlog_ex("Failed opening file " + filename_to_str(_filename) + " for writing"); throw spdlog_ex("Failed opening file " + filename_to_str(_filename) + " for writing");
} }
void reopen(bool truncate) void reopen(bool truncate)
{ {
if (_filename.empty()) if (_filename.empty())
throw spdlog_ex("Failed re opening file - was not opened before"); throw spdlog_ex("Failed re opening file - was not opened before");
open(_filename, truncate); open(_filename, truncate);
} }
void flush() void flush()
{ {
std::fflush(_fd); std::fflush(_fd);
} }
void close() void close()
{ {
if (_fd) if (_fd)
{ {
std::fclose(_fd); std::fclose(_fd);
_fd = nullptr; _fd = nullptr;
} }
} }
void write(const log_msg& msg) void write(const log_msg& msg)
{ {
size_t msg_size = msg.formatted.size(); size_t msg_size = msg.formatted.size();
auto data = msg.formatted.data(); auto data = msg.formatted.data();
if (std::fwrite(data, 1, msg_size, _fd) != msg_size) if (std::fwrite(data, 1, msg_size, _fd) != msg_size)
throw spdlog_ex("Failed writing to file " + filename_to_str(_filename)); throw spdlog_ex("Failed writing to file " + filename_to_str(_filename));
if (_force_flush) if (_force_flush)
std::fflush(_fd); std::fflush(_fd);
} }
long size() long size()
{ {
if (!_fd) if (!_fd)
throw spdlog_ex("Cannot use size() on closed file " + filename_to_str(_filename)); throw spdlog_ex("Cannot use size() on closed file " + filename_to_str(_filename));
auto pos = ftell(_fd); auto pos = ftell(_fd);
if (fseek(_fd, 0, SEEK_END) != 0) if (fseek(_fd, 0, SEEK_END) != 0)
throw spdlog_ex("fseek failed on file " + filename_to_str(_filename)); throw spdlog_ex("fseek failed on file " + filename_to_str(_filename));
auto file_size = ftell(_fd); auto file_size = ftell(_fd);
if(fseek(_fd, pos, SEEK_SET) !=0) if(fseek(_fd, pos, SEEK_SET) !=0)
throw spdlog_ex("fseek failed on file " + filename_to_str(_filename)); throw spdlog_ex("fseek failed on file " + filename_to_str(_filename));
if (file_size == -1) if (file_size == -1)
throw spdlog_ex("ftell failed on file " + filename_to_str(_filename)); throw spdlog_ex("ftell failed on file " + filename_to_str(_filename));
return file_size; return file_size;
} }
const filename_t& filename() const const filename_t& filename() const
{ {
return _filename; return _filename;
} }
static bool file_exists(const filename_t& name) static bool file_exists(const filename_t& name)
{ {
return os::file_exists(name); return os::file_exists(name);
} }
private: private:
FILE* _fd; FILE* _fd;
filename_t _filename; filename_t _filename;
bool _force_flush; bool _force_flush;
}; };
} }
} }
This diff is collapsed.
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
#include <spdlog/common.h> #include <spdlog/common.h>
#include <spdlog/details/log_msg.h> #include <spdlog/details/log_msg.h>
#include <string> #include <string>
// Line logger class - aggregates operator<< calls to fast ostream // Line logger class - aggregates operator<< calls to fast ostream
// and logs upon destruction // and logs upon destruction
namespace spdlog namespace spdlog
{ {
// Forward declaration // Forward declaration
class logger; class logger;
namespace details namespace details
{ {
class line_logger class line_logger
{ {
public: public:
line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled); line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled);
// No copy intended. Only move // No copy intended. Only move
line_logger(const line_logger& other) = delete; line_logger(const line_logger& other) = delete;
line_logger& operator=(const line_logger&) = delete; line_logger& operator=(const line_logger&) = delete;
line_logger& operator=(line_logger&&) = delete; line_logger& operator=(line_logger&&) = delete;
line_logger(line_logger&& other); line_logger(line_logger&& other);
//Log the log message using the callback logger //Log the log message using the callback logger
~line_logger(); ~line_logger();
// //
// Support for format string with variadic args // Support for format string with variadic args
// //
void write(const char* what); void write(const char* what);
template <typename... Args> template <typename... Args>
void write(const char* fmt, const Args&... args); void write(const char* fmt, const Args&... args);
// //
// Support for operator<< // Support for operator<<
// //
line_logger& operator<<(const char* what); line_logger& operator<<(const char* what);
line_logger& operator<<(const std::string& what); line_logger& operator<<(const std::string& what);
line_logger& operator<<(int what); line_logger& operator<<(int what);
line_logger& operator<<(unsigned int what); line_logger& operator<<(unsigned int what);
line_logger& operator<<(long what); line_logger& operator<<(long what);
line_logger& operator<<(unsigned long what); line_logger& operator<<(unsigned long what);
line_logger& operator<<(long long what); line_logger& operator<<(long long what);
line_logger& operator<<(unsigned long long what); line_logger& operator<<(unsigned long long what);
line_logger& operator<<(double what); line_logger& operator<<(double what);
line_logger& operator<<(long double what); line_logger& operator<<(long double what);
line_logger& operator<<(float what); line_logger& operator<<(float what);
line_logger& operator<<(char what); line_logger& operator<<(char what);
//Support user types which implements operator<< //Support user types which implements operator<<
template<typename T> template<typename T>
line_logger& operator<<(const T& what); line_logger& operator<<(const T& what);
void disable(); void disable();
bool is_enabled() const; bool is_enabled() const;
private: private:
logger* _callback_logger; logger* _callback_logger;
log_msg _log_msg; log_msg _log_msg;
bool _enabled; bool _enabled;
}; };
} //Namespace details } //Namespace details
} // Namespace spdlog } // Namespace spdlog
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
#include <type_traits> #include <type_traits>
#include <spdlog/details/line_logger_fwd.h> #include <spdlog/details/line_logger_fwd.h>
#include <spdlog/common.h> #include <spdlog/common.h>
#include <spdlog/logger.h> #include <spdlog/logger.h>
#include <string> #include <string>
#include <utility> #include <utility>
// Line logger class - aggregates operator<< calls to fast ostream // Line logger class - aggregates operator<< calls to fast ostream
// and logs upon destruction // and logs upon destruction
inline spdlog::details::line_logger::line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled): inline spdlog::details::line_logger::line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled):
_callback_logger(callback_logger), _callback_logger(callback_logger),
_log_msg(msg_level), _log_msg(msg_level),
_enabled(enabled) _enabled(enabled)
{} {}
inline spdlog::details::line_logger::line_logger(line_logger&& other) : inline spdlog::details::line_logger::line_logger(line_logger&& other) :
_callback_logger(other._callback_logger), _callback_logger(other._callback_logger),
_log_msg(std::move(other._log_msg)), _log_msg(std::move(other._log_msg)),
_enabled(other._enabled) _enabled(other._enabled)
{ {
other.disable(); other.disable();
} }
//Log the log message using the callback logger //Log the log message using the callback logger
inline spdlog::details::line_logger::~line_logger() inline spdlog::details::line_logger::~line_logger()
{ {
if (_enabled) if (_enabled)
{ {
#ifndef SPDLOG_NO_NAME #ifndef SPDLOG_NO_NAME
_log_msg.logger_name = _callback_logger->name(); _log_msg.logger_name = _callback_logger->name();
#endif #endif
#ifndef SPDLOG_NO_DATETIME #ifndef SPDLOG_NO_DATETIME
_log_msg.time = os::now(); _log_msg.time = os::now();
#endif #endif
#ifndef SPDLOG_NO_THREAD_ID #ifndef SPDLOG_NO_THREAD_ID
_log_msg.thread_id = os::thread_id(); _log_msg.thread_id = os::thread_id();
#endif #endif
_callback_logger->_log_msg(_log_msg); _callback_logger->_log_msg(_log_msg);
} }
} }
// //
// Support for format string with variadic args // Support for format string with variadic args
// //
inline void spdlog::details::line_logger::write(const char* what) inline void spdlog::details::line_logger::write(const char* what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
} }
template <typename... Args> template <typename... Args>
inline void spdlog::details::line_logger::write(const char* fmt, const Args&... args) inline void spdlog::details::line_logger::write(const char* fmt, const Args&... args)
{ {
if (!_enabled) if (!_enabled)
return; return;
try try
{ {
_log_msg.raw.write(fmt, args...); _log_msg.raw.write(fmt, args...);
} }
catch (const fmt::FormatError& e) catch (const fmt::FormatError& e)
{ {
throw spdlog_ex(fmt::format("formatting error while processing format string '{}': {}", fmt, e.what())); throw spdlog_ex(fmt::format("formatting error while processing format string '{}': {}", fmt, e.what()));
} }
} }
// //
// Support for operator<< // Support for operator<<
// //
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(const char* what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(const char* what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(const std::string& what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(const std::string& what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(int what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(int what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(unsigned int what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(unsigned int what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(long what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(long what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(unsigned long what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(unsigned long what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(long long what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(long long what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(unsigned long long what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(unsigned long long what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(double what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(double what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(long double what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(long double what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(float what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(float what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(char what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(char what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw << what; _log_msg.raw << what;
return *this; return *this;
} }
//Support user types which implements operator<< //Support user types which implements operator<<
template<typename T> template<typename T>
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(const T& what) inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(const T& what)
{ {
if (_enabled) if (_enabled)
_log_msg.raw.write("{}", what); _log_msg.raw.write("{}", what);
return *this; return *this;
} }
inline void spdlog::details::line_logger::disable() inline void spdlog::details::line_logger::disable()
{ {
_enabled = false; _enabled = false;
} }
inline bool spdlog::details::line_logger::is_enabled() const inline bool spdlog::details::line_logger::is_enabled() const
{ {
return _enabled; return _enabled;
} }
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
#include <spdlog/common.h> #include <spdlog/common.h>
#include <spdlog/details/format.h> #include <spdlog/details/format.h>
#include <string> #include <string>
#include <utility> #include <utility>
namespace spdlog namespace spdlog
{ {
namespace details namespace details
{ {
struct log_msg struct log_msg
{ {
log_msg() = default; log_msg() = default;
log_msg(level::level_enum l): log_msg(level::level_enum l):
logger_name(), logger_name(),
level(l), level(l),
raw(), raw(),
formatted() {} formatted() {}
log_msg(const log_msg& other) : log_msg(const log_msg& other) :
logger_name(other.logger_name), logger_name(other.logger_name),
level(other.level), level(other.level),
time(other.time), time(other.time),
thread_id(other.thread_id) thread_id(other.thread_id)
{ {
if (other.raw.size()) if (other.raw.size())
raw << fmt::BasicStringRef<char>(other.raw.data(), other.raw.size()); raw << fmt::BasicStringRef<char>(other.raw.data(), other.raw.size());
if (other.formatted.size()) if (other.formatted.size())
formatted << fmt::BasicStringRef<char>(other.formatted.data(), other.formatted.size()); formatted << fmt::BasicStringRef<char>(other.formatted.data(), other.formatted.size());
} }
log_msg(log_msg&& other) : log_msg(log_msg&& other) :
logger_name(std::move(other.logger_name)), logger_name(std::move(other.logger_name)),
level(other.level), level(other.level),
time(std::move(other.time)), time(std::move(other.time)),
thread_id(other.thread_id), thread_id(other.thread_id),
raw(std::move(other.raw)), raw(std::move(other.raw)),
formatted(std::move(other.formatted)) formatted(std::move(other.formatted))
{ {
other.clear(); other.clear();
} }
log_msg& operator=(log_msg&& other) log_msg& operator=(log_msg&& other)
{ {
if (this == &other) if (this == &other)
return *this; return *this;
logger_name = std::move(other.logger_name); logger_name = std::move(other.logger_name);
level = other.level; level = other.level;
time = std::move(other.time); time = std::move(other.time);
thread_id = other.thread_id; thread_id = other.thread_id;
raw = std::move(other.raw); raw = std::move(other.raw);
formatted = std::move(other.formatted); formatted = std::move(other.formatted);
other.clear(); other.clear();
return *this; return *this;
} }
void clear() void clear()
{ {
level = level::off; level = level::off;
raw.clear(); raw.clear();
formatted.clear(); formatted.clear();
} }
std::string logger_name; std::string logger_name;
level::level_enum level; level::level_enum level;
log_clock::time_point time; log_clock::time_point time;
size_t thread_id; size_t thread_id;
fmt::MemoryWriter raw; fmt::MemoryWriter raw;
fmt::MemoryWriter formatted; fmt::MemoryWriter formatted;
}; };
} }
} }
This diff is collapsed.
This diff is collapsed.
...@@ -24,21 +24,21 @@ struct null_mutex ...@@ -24,21 +24,21 @@ struct null_mutex
struct null_atomic_int struct null_atomic_int
{ {
int value; int value;
null_atomic_int() = default; null_atomic_int() = default;
null_atomic_int(int val):value(val) null_atomic_int(int val):value(val)
{} {}
int load(std::memory_order) const int load(std::memory_order) const
{ {
return value; return value;
} }
void store(int val) void store(int val)
{ {
value = val; value = val;
} }
}; };
} }
......
This diff is collapsed.
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
// Loggers registy of unique name->logger pointer // Loggers registy of unique name->logger pointer
// An attempt to create a logger with an already existing name will be ignored // An attempt to create a logger with an already existing name will be ignored
// If user requests a non existing logger, nullptr will be returned // If user requests a non existing logger, nullptr will be returned
// This class is thread safe // This class is thread safe
#include <spdlog/details/null_mutex.h> #include <spdlog/details/null_mutex.h>
#include <spdlog/logger.h> #include <spdlog/logger.h>
#include <spdlog/async_logger.h> #include <spdlog/async_logger.h>
#include <spdlog/common.h> #include <spdlog/common.h>
#include <chrono> #include <chrono>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
namespace spdlog namespace spdlog
{ {
namespace details namespace details
{ {
template <class Mutex> class registry_t template <class Mutex> class registry_t
{ {
public: public:
void register_logger(std::shared_ptr<logger> logger) void register_logger(std::shared_ptr<logger> logger)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
auto logger_name = logger->name(); auto logger_name = logger->name();
throw_if_exists(logger_name); throw_if_exists(logger_name);
_loggers[logger_name] = logger; _loggers[logger_name] = logger;
} }
std::shared_ptr<logger> get(const std::string& logger_name) std::shared_ptr<logger> get(const std::string& logger_name)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
auto found = _loggers.find(logger_name); auto found = _loggers.find(logger_name);
return found == _loggers.end() ? nullptr : found->second; return found == _loggers.end() ? nullptr : found->second;
} }
template<class It> template<class It>
std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
throw_if_exists(logger_name); throw_if_exists(logger_name);
std::shared_ptr<logger> new_logger; std::shared_ptr<logger> new_logger;
if (_async_mode) if (_async_mode)
new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms); new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms);
else else
new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end); new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
if (_formatter) if (_formatter)
new_logger->set_formatter(_formatter); new_logger->set_formatter(_formatter);
new_logger->set_level(_level); new_logger->set_level(_level);
//Add to registry //Add to registry
_loggers[logger_name] = new_logger; _loggers[logger_name] = new_logger;
return new_logger; return new_logger;
} }
void drop(const std::string& logger_name) void drop(const std::string& logger_name)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_loggers.erase(logger_name); _loggers.erase(logger_name);
} }
void drop_all() void drop_all()
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_loggers.clear(); _loggers.clear();
} }
std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks) std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks)
{ {
return create(logger_name, sinks.begin(), sinks.end()); return create(logger_name, sinks.begin(), sinks.end());
} }
std::shared_ptr<logger> create(const std::string& logger_name, sink_ptr sink) std::shared_ptr<logger> create(const std::string& logger_name, sink_ptr sink)
{ {
return create(logger_name, { sink }); return create(logger_name, { sink });
} }
void formatter(formatter_ptr f) void formatter(formatter_ptr f)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_formatter = f; _formatter = f;
for (auto& l : _loggers) for (auto& l : _loggers)
l.second->set_formatter(_formatter); l.second->set_formatter(_formatter);
} }
void set_pattern(const std::string& pattern) void set_pattern(const std::string& pattern)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_formatter = std::make_shared<pattern_formatter>(pattern); _formatter = std::make_shared<pattern_formatter>(pattern);
for (auto& l : _loggers) for (auto& l : _loggers)
l.second->set_formatter(_formatter); l.second->set_formatter(_formatter);
} }
void set_level(level::level_enum log_level) void set_level(level::level_enum log_level)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
for (auto& l : _loggers) for (auto& l : _loggers)
l.second->set_level(log_level); l.second->set_level(log_level);
_level = log_level; _level = log_level;
} }
void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms) void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_async_mode = true; _async_mode = true;
_async_q_size = q_size; _async_q_size = q_size;
_overflow_policy = overflow_policy; _overflow_policy = overflow_policy;
_worker_warmup_cb = worker_warmup_cb; _worker_warmup_cb = worker_warmup_cb;
_flush_interval_ms = flush_interval_ms; _flush_interval_ms = flush_interval_ms;
} }
void set_sync_mode() void set_sync_mode()
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_async_mode = false; _async_mode = false;
} }
static registry_t<Mutex>& instance() static registry_t<Mutex>& instance()
{ {
static registry_t<Mutex> s_instance; static registry_t<Mutex> s_instance;
return s_instance; return s_instance;
} }
private: private:
registry_t<Mutex>() {} registry_t<Mutex>() {}
registry_t<Mutex>(const registry_t<Mutex>&) = delete; registry_t<Mutex>(const registry_t<Mutex>&) = delete;
registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete; registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete;
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())
throw spdlog_ex("logger with name '" + logger_name + "' already exists"); throw spdlog_ex("logger with name '" + logger_name + "' already exists");
} }
Mutex _mutex; Mutex _mutex;
std::unordered_map <std::string, std::shared_ptr<logger>> _loggers; std::unordered_map <std::string, std::shared_ptr<logger>> _loggers;
formatter_ptr _formatter; formatter_ptr _formatter;
level::level_enum _level = level::info; level::level_enum _level = level::info;
bool _async_mode = false; bool _async_mode = false;
size_t _async_q_size = 0; size_t _async_q_size = 0;
async_overflow_policy _overflow_policy = async_overflow_policy::block_retry; async_overflow_policy _overflow_policy = async_overflow_policy::block_retry;
std::function<void()> _worker_warmup_cb = nullptr; std::function<void()> _worker_warmup_cb = nullptr;
std::chrono::milliseconds _flush_interval_ms; std::chrono::milliseconds _flush_interval_ms;
}; };
#ifdef SPDLOG_NO_REGISTRY_MUTEX #ifdef SPDLOG_NO_REGISTRY_MUTEX
typedef registry_t<spdlog::details::null_mutex> registry; typedef registry_t<spdlog::details::null_mutex> registry;
#else #else
typedef registry_t<std::mutex> registry; typedef registry_t<std::mutex> registry;
#endif #endif
} }
} }
This diff is collapsed.
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
#include <spdlog/details/log_msg.h> #include <spdlog/details/log_msg.h>
#include <vector> #include <vector>
#include <string> #include <string>
#include <memory> #include <memory>
namespace spdlog namespace spdlog
{ {
namespace details namespace details
{ {
class flag_formatter; class flag_formatter;
} }
class formatter class formatter
{ {
public: public:
virtual ~formatter() {} virtual ~formatter() {}
virtual void format(details::log_msg& msg) = 0; virtual void format(details::log_msg& msg) = 0;
}; };
class pattern_formatter : public formatter class pattern_formatter : public formatter
{ {
public: public:
explicit pattern_formatter(const std::string& pattern); explicit pattern_formatter(const std::string& pattern);
pattern_formatter(const pattern_formatter&) = delete; pattern_formatter(const pattern_formatter&) = delete;
pattern_formatter& operator=(const pattern_formatter&) = delete; pattern_formatter& operator=(const pattern_formatter&) = delete;
void format(details::log_msg& msg) override; void format(details::log_msg& msg) override;
private: private:
const std::string _pattern; const std::string _pattern;
std::vector<std::unique_ptr<details::flag_formatter>> _formatters; std::vector<std::unique_ptr<details::flag_formatter>> _formatters;
void handle_flag(char flag); void handle_flag(char flag);
void compile_pattern(const std::string& pattern); void compile_pattern(const std::string& pattern);
}; };
} }
#include <spdlog/details/pattern_formatter_impl.h> #include <spdlog/details/pattern_formatter_impl.h>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#pragma once #pragma once
#include <cstdio> #include <cstdio>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <ostream> #include <ostream>
#include <chrono> #include <chrono>
#include <exception> #include <exception>
#include "catch.hpp" #include "catch.hpp"
#include "utils.h" #include "utils.h"
#include "../include/spdlog/spdlog.h" #include "../include/spdlog/spdlog.h"
#include "../include/spdlog/sinks/null_sink.h" #include "../include/spdlog/sinks/null_sink.h"
#include "../include/spdlog/sinks/ostream_sink.h" #include "../include/spdlog/sinks/ostream_sink.h"
This diff is collapsed.
This diff is collapsed.
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