Commit 0d263598 authored by gabime's avatar gabime

astyle

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