Merge branch 'master' of github.com:gabime/spdlog into improvement/buck

pull/448/head
njlr 8 years ago
commit 1afa301a1c

@ -69,7 +69,7 @@ Time needed to log 1,000,000 lines in asynchronous mode, i.e. the time it takes
## Buck ## Buck
The test, examples and benchmarks can be run using [Buck](https://www.buckbuild.com): The tests, examples and benchmarks can be run using [Buck](https://www.buckbuild.com):
```bash ```bash
buck run example/ buck run example/
@ -159,13 +159,13 @@ int main(int, char*[])
err_handler_example(); err_handler_example();
// Apply a function on all registered loggers // Apply a function on all registered loggers
spd::apply_all([&](std::shared_ptr<spdlog::logger> l) spd::apply_all([&](std::shared_ptr<spd::logger> l)
{ {
l->info("End of example."); l->info("End of example.");
}); });
// Release and close all loggers // Release and close all loggers
spdlog::drop_all(); spd::drop_all();
} }
// Exceptions will only be thrown upon failed logger or sink construction (not during logging) // Exceptions will only be thrown upon failed logger or sink construction (not during logging)
catch (const spd::spdlog_ex& ex) catch (const spd::spdlog_ex& ex)
@ -178,7 +178,7 @@ int main(int, char*[])
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); spd::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);
@ -216,7 +216,7 @@ void user_defined_example()
// //
void err_handler_example() void err_handler_example()
{ {
spdlog::set_error_handler([](const std::string& msg) { spd::set_error_handler([](const std::string& msg) {
std::cerr << "my err handler: " << msg << std::endl; std::cerr << "my err handler: " << msg << std::endl;
}); });
// (or logger->set_error_handler(..) to set for specific logger) // (or logger->set_error_handler(..) to set for specific logger)

@ -31,7 +31,7 @@ namespace details
class async_log_helper; class async_log_helper;
} }
class async_logger :public logger class async_logger SPDLOG_FINAL :public logger
{ {
public: public:
template<class It> template<class It>
@ -61,7 +61,7 @@ public:
const std::function<void()>& worker_teardown_cb = nullptr); const std::function<void()>& worker_teardown_cb = nullptr);
//Wait for the queue to be empty, and flush synchronously //Wait for the queue to be empty, and flush synchronously
//Warning: this can potentialy last forever as we wait it to complete //Warning: this can potentially last forever as we wait it to complete
void flush() override; void flush() override;
// Error handler // Error handler

@ -29,6 +29,11 @@
#define SPDLOG_CONSTEXPR constexpr #define SPDLOG_CONSTEXPR constexpr
#endif #endif
// See tweakme.h
#if !defined(SPDLOG_FINAL)
#define SPDLOG_FINAL
#endif
#if defined(__GNUC__) || defined(__clang__) #if defined(__GNUC__) || defined(__clang__)
#define SPDLOG_DEPRECATED __attribute__((deprecated)) #define SPDLOG_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER) #elif defined(_MSC_VER)

@ -9,8 +9,6 @@
// If the internal queue of log messages reaches its max size, // If the internal queue of log messages reaches its max size,
// then the client call will block until there is more room. // then the client call will block until there is more room.
// //
// If the back thread throws during logging, a spdlog::spdlog_ex exception
// will be thrown in client's thread when tries to log the next message
#pragma once #pragma once
@ -62,11 +60,15 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
logger_name(std::move(other.logger_name)), logger_name(std::move(other.logger_name)),
level(std::move(other.level)), level(std::move(other.level)),
time(std::move(other.time)), time(std::move(other.time)),
thread_id(other.thread_id),
txt(std::move(other.txt)), txt(std::move(other.txt)),
msg_type(std::move(other.msg_type)) msg_type(std::move(other.msg_type))
{} {}
async_msg(async_msg_type m_type):msg_type(m_type) async_msg(async_msg_type m_type):
level(level::info),
thread_id(0),
msg_type(m_type)
{} {}
async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT
@ -177,7 +179,7 @@ private:
void handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush); void handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush);
// sleep,yield or return immediatly using the time passed since last message as a hint // sleep,yield or return immediately using the time passed since last message as a hint
static void sleep_or_yield(const spdlog::log_clock::time_point& now, const log_clock::time_point& last_op_time); static void sleep_or_yield(const spdlog::log_clock::time_point& now, const log_clock::time_point& last_op_time);
// wait until the queue is empty // wait until the queue is empty

@ -7,7 +7,6 @@
// 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
// Throw spdlog_ex exception on errors // Throw spdlog_ex exception on errors
#include <spdlog/details/os.h> #include <spdlog/details/os.h>

@ -18,11 +18,11 @@ template<class It>
inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end): inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end):
_name(logger_name), _name(logger_name),
_sinks(begin, end), _sinks(begin, end),
_formatter(std::make_shared<pattern_formatter>("%+")) _formatter(std::make_shared<pattern_formatter>("%+")),
_level(level::info),
_flush_level(level::off),
_last_err_time(0)
{ {
_level = level::info;
_flush_level = level::off;
_last_err_time = 0;
_err_handler = [this](const std::string &msg) _err_handler = [this](const std::string &msg)
{ {
this->_default_err_handler(msg); this->_default_err_handler(msg);
@ -195,6 +195,63 @@ inline void spdlog::logger::critical(const T& msg)
log(level::critical, msg); log(level::critical, msg);
} }
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
#include <codecvt>
template <typename... Args>
inline void spdlog::logger::log(level::level_enum lvl, const wchar_t* msg)
{
std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
log(lvl, conv.to_bytes(msg));
}
template <typename... Args>
inline void spdlog::logger::log(level::level_enum lvl, const wchar_t* fmt, const Args&... args)
{
fmt::WMemoryWriter wWriter;
wWriter.write(fmt, args...);
log(lvl, wWriter.c_str());
}
template <typename... Args>
inline void spdlog::logger::trace(const wchar_t* fmt, const Args&... args)
{
log(level::trace, fmt, args...);
}
template <typename... Args>
inline void spdlog::logger::debug(const wchar_t* fmt, const Args&... args)
{
log(level::debug, fmt, args...);
}
template <typename... Args>
inline void spdlog::logger::info(const wchar_t* fmt, const Args&... args)
{
log(level::info, fmt, args...);
}
template <typename... Args>
inline void spdlog::logger::warn(const wchar_t* fmt, const Args&... args)
{
log(level::warn, fmt, args...);
}
template <typename... Args>
inline void spdlog::logger::error(const wchar_t* fmt, const Args&... args)
{
log(level::err, fmt, args...);
}
template <typename... Args>
inline void spdlog::logger::critical(const wchar_t* fmt, const Args&... args)
{
log(level::critical, fmt, args...);
}
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT

@ -12,8 +12,9 @@
#include <string> #include <string>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <stdio.h> #include <algorithm>
#include <string.h> #include <cstring>
#include <cstdlib>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
@ -364,6 +365,22 @@ inline std::string filename_to_str(const filename_t& filename)
} }
#endif #endif
inline std::string errno_to_string(char [256], char* res)
{
return std::string(res);
}
inline std::string errno_to_string(char buf[256], int res)
{
if (res == 0)
{
return std::string(buf);
}
else
{
return "Unknown error";
}
}
// Return errno string (thread safe) // Return errno string (thread safe)
inline std::string errno_str(int err_num) inline std::string errno_str(int err_num)
@ -375,7 +392,7 @@ inline std::string errno_str(int err_num)
if(strerror_s(buf, buf_size, err_num) == 0) if(strerror_s(buf, buf_size, err_num) == 0)
return std::string(buf); return std::string(buf);
else else
return "Unkown error"; return "Unknown error";
#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || defined(__SUNPRO_CC) || \ #elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || defined(__SUNPRO_CC) || \
((_POSIX_C_SOURCE >= 200112L) && ! defined(_GNU_SOURCE)) // posix version ((_POSIX_C_SOURCE >= 200112L) && ! defined(_GNU_SOURCE)) // posix version
@ -383,10 +400,11 @@ inline std::string errno_str(int err_num)
if (strerror_r(err_num, buf, buf_size) == 0) if (strerror_r(err_num, buf, buf_size) == 0)
return std::string(buf); return std::string(buf);
else else
return "Unkown error"; return "Unknown error";
#else // gnu version (might not use the given buf, so its retval pointer must be used) #else // gnu version (might not use the given buf, so its retval pointer must be used)
return std::string(strerror_r(err_num, buf, buf_size)); auto err = strerror_r(err_num, buf, buf_size); // let compiler choose type
return errno_to_string(buf, err); // use overloading to select correct stringify function
#endif #endif
} }
@ -401,6 +419,36 @@ inline int pid()
} }
// Detrmine if the terminal supports colors
// Source: https://github.com/agauniyal/rang/
inline bool is_color_terminal()
{
#ifdef _WIN32
return true;
#else
static constexpr const char* Terms[] =
{
"ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm",
"linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm"
};
const char *env_p = std::getenv("TERM");
if (env_p == nullptr)
{
return false;
}
static const bool result = std::any_of(
std::begin(Terms), std::end(Terms), [&](const char* term)
{
return std::strstr(env_p, term) != nullptr;
});
return result;
#endif
}
} //os } //os
} //details } //details
} //spdlog } //spdlog

@ -99,7 +99,7 @@ static const days_array& full_days()
static const days_array arr{ { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" } }; static const days_array arr{ { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" } };
return arr; return arr;
} }
class A_formatter:public flag_formatter class A_formatter SPDLOG_FINAL :public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -128,7 +128,7 @@ static const months_array& full_months()
static const months_array arr{ { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" } }; static const months_array arr{ { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" } };
return arr; return arr;
} }
class B_formatter:public flag_formatter class B_formatter SPDLOG_FINAL :public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -153,7 +153,7 @@ static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v
//Date and time representation (Thu Aug 23 15:35:46 2014) //Date and time representation (Thu Aug 23 15:35:46 2014)
class c_formatter:public flag_formatter class c_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -164,7 +164,7 @@ class c_formatter:public flag_formatter
// year - 2 digit // year - 2 digit
class C_formatter:public flag_formatter class C_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -175,7 +175,7 @@ class C_formatter:public flag_formatter
// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01 // Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01
class D_formatter:public flag_formatter class D_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -185,7 +185,7 @@ class D_formatter:public flag_formatter
// year - 4 digit // year - 4 digit
class Y_formatter:public flag_formatter class Y_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -194,7 +194,7 @@ class Y_formatter:public flag_formatter
}; };
// month 1-12 // month 1-12
class m_formatter:public flag_formatter class m_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -203,7 +203,7 @@ class m_formatter:public flag_formatter
}; };
// day of month 1-31 // day of month 1-31
class d_formatter:public flag_formatter class d_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -212,7 +212,7 @@ class d_formatter:public flag_formatter
}; };
// hours in 24 format 0-23 // hours in 24 format 0-23
class H_formatter:public flag_formatter class H_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -221,7 +221,7 @@ class H_formatter:public flag_formatter
}; };
// hours in 12 format 1-12 // hours in 12 format 1-12
class I_formatter:public flag_formatter class I_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -230,7 +230,7 @@ class I_formatter:public flag_formatter
}; };
// minutes 0-59 // minutes 0-59
class M_formatter:public flag_formatter class M_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -239,7 +239,7 @@ class M_formatter:public flag_formatter
}; };
// seconds 0-59 // seconds 0-59
class S_formatter:public flag_formatter class S_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -248,7 +248,7 @@ class S_formatter:public flag_formatter
}; };
// milliseconds // milliseconds
class e_formatter:public flag_formatter class e_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm&) override void format(details::log_msg& msg, const std::tm&) override
{ {
@ -259,7 +259,7 @@ class e_formatter:public flag_formatter
}; };
// microseconds // microseconds
class f_formatter:public flag_formatter class f_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm&) override void format(details::log_msg& msg, const std::tm&) override
{ {
@ -270,7 +270,7 @@ class f_formatter:public flag_formatter
}; };
// nanoseconds // nanoseconds
class F_formatter:public flag_formatter class F_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm&) override void format(details::log_msg& msg, const std::tm&) override
{ {
@ -281,7 +281,7 @@ class F_formatter:public flag_formatter
}; };
// AM/PM // AM/PM
class p_formatter:public flag_formatter class p_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -291,7 +291,7 @@ class p_formatter:public flag_formatter
// 12 hour clock 02:55:02 pm // 12 hour clock 02:55:02 pm
class r_formatter:public flag_formatter class r_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -300,7 +300,7 @@ class r_formatter:public flag_formatter
}; };
// 24-hour HH:MM time, equivalent to %H:%M // 24-hour HH:MM time, equivalent to %H:%M
class R_formatter:public flag_formatter class R_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -309,7 +309,7 @@ class R_formatter:public flag_formatter
}; };
// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S // ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
class T_formatter:public flag_formatter class T_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -319,12 +319,12 @@ class T_formatter:public flag_formatter
// ISO 8601 offset from UTC in timezone (+-HH:MM) // ISO 8601 offset from UTC in timezone (+-HH:MM)
class z_formatter:public flag_formatter class z_formatter SPDLOG_FINAL:public flag_formatter
{ {
public: public:
const std::chrono::seconds cache_refresh = std::chrono::seconds(5); const std::chrono::seconds cache_refresh = std::chrono::seconds(5);
z_formatter():_last_update(std::chrono::seconds(0)) z_formatter():_last_update(std::chrono::seconds(0)), _offset_minutes(0)
{} {}
z_formatter(const z_formatter&) = delete; z_formatter(const z_formatter&) = delete;
z_formatter& operator=(const z_formatter&) = delete; z_formatter& operator=(const z_formatter&) = delete;
@ -376,7 +376,7 @@ private:
// Thread id // Thread id
class t_formatter:public flag_formatter class t_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm&) override void format(details::log_msg& msg, const std::tm&) override
{ {
@ -385,7 +385,7 @@ class t_formatter:public flag_formatter
}; };
// Current pid // Current pid
class pid_formatter:public flag_formatter class pid_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm&) override void format(details::log_msg& msg, const std::tm&) override
{ {
@ -394,7 +394,7 @@ class pid_formatter:public flag_formatter
}; };
class v_formatter:public flag_formatter class v_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm&) override void format(details::log_msg& msg, const std::tm&) override
{ {
@ -402,7 +402,7 @@ class v_formatter:public flag_formatter
} }
}; };
class ch_formatter:public flag_formatter class ch_formatter SPDLOG_FINAL:public flag_formatter
{ {
public: public:
explicit ch_formatter(char ch): _ch(ch) explicit ch_formatter(char ch): _ch(ch)
@ -417,7 +417,7 @@ private:
//aggregate user chars to display as is //aggregate user chars to display as is
class aggregate_formatter:public flag_formatter class aggregate_formatter SPDLOG_FINAL:public flag_formatter
{ {
public: public:
aggregate_formatter() aggregate_formatter()
@ -436,7 +436,7 @@ private:
// Full info formatter // Full info formatter
// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v // pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
class full_formatter:public flag_formatter class full_formatter SPDLOG_FINAL:public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm& tm_time) override void format(details::log_msg& msg, const std::tm& tm_time) override
{ {
@ -645,7 +645,7 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::pid_formatter())); _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::pid_formatter()));
break; break;
default: //Unkown flag appears as is default: //Unknown flag appears as is
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter('%'))); _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter('%')));
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter(flag))); _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter(flag)));
break; break;

@ -25,7 +25,7 @@ public:
virtual void format(details::log_msg& msg) = 0; virtual void format(details::log_msg& msg) = 0;
}; };
class pattern_formatter : public formatter class pattern_formatter SPDLOG_FINAL : public formatter
{ {
public: public:

@ -43,6 +43,16 @@ public:
template <typename Arg1, typename... Args> void warn(const char* fmt, const Arg1&, const Args&... args); template <typename Arg1, typename... Args> void warn(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void error(const char* fmt, const Arg1&, const Args&... args); template <typename Arg1, typename... Args> void error(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void critical(const char* fmt, const Arg1&, const Args&... args); template <typename Arg1, typename... Args> void critical(const char* fmt, const Arg1&, const Args&... args);
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
template <typename... Args> void log(level::level_enum lvl, const wchar_t* msg);
template <typename... Args> void log(level::level_enum lvl, const wchar_t* fmt, const Args&... args);
template <typename... Args> void trace(const wchar_t* fmt, const Args&... args);
template <typename... Args> void debug(const wchar_t* fmt, const Args&... args);
template <typename... Args> void info(const wchar_t* fmt, const Args&... args);
template <typename... Args> void warn(const wchar_t* fmt, const Args&... args);
template <typename... Args> void error(const wchar_t* fmt, const Args&... args);
template <typename... Args> void critical(const wchar_t* fmt, const Args&... args);
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
template <typename T> void log(level::level_enum lvl, const T&); template <typename T> void log(level::level_enum lvl, const T&);
template <typename T> void trace(const T&); template <typename T> void trace(const T&);

@ -12,6 +12,12 @@
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <android/log.h> #include <android/log.h>
#include <thread>
#include <chrono>
#if !defined(SPDLOG_ANDROID_RETRIES)
#define SPDLOG_ANDROID_RETRIES 2
#endif
namespace spdlog namespace spdlog
{ {
@ -25,15 +31,23 @@ namespace sinks
class android_sink : public sink class android_sink : public sink
{ {
public: public:
explicit android_sink(const std::string& tag = "spdlog"): _tag(tag) {} explicit android_sink(const std::string& tag = "spdlog", bool use_raw_msg = false): _tag(tag), _use_raw_msg(use_raw_msg) {}
void log(const details::log_msg& msg) override void log(const details::log_msg& msg) override
{ {
const android_LogPriority priority = convert_to_android(msg.level); const android_LogPriority priority = convert_to_android(msg.level);
const char *msg_output = (_use_raw_msg ? msg.raw.c_str() : msg.formatted.c_str());
// See system/core/liblog/logger_write.c for explanation of return value // See system/core/liblog/logger_write.c for explanation of return value
const int ret = __android_log_write( int ret = __android_log_write(priority, _tag.c_str(), msg_output);
priority, _tag.c_str(), msg.formatted.c_str() int retry_count = 0;
); while ((ret == -11/*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES))
{
std::this_thread::sleep_for(std::chrono::milliseconds(5));
ret = __android_log_write(priority, _tag.c_str(), msg_output);
retry_count++;
}
if (ret < 0) if (ret < 0)
{ {
throw spdlog_ex("__android_log_write() failed", ret); throw spdlog_ex("__android_log_write() failed", ret);
@ -67,6 +81,7 @@ private:
} }
std::string _tag; std::string _tag;
bool _use_raw_msg;
}; };
} }

@ -7,6 +7,7 @@
#include <spdlog/sinks/base_sink.h> #include <spdlog/sinks/base_sink.h>
#include <spdlog/common.h> #include <spdlog/common.h>
#include <spdlog/details/os.h>
#include <string> #include <string>
#include <map> #include <map>
@ -21,7 +22,7 @@ namespace sinks
* the output with an ANSI escape sequence color code depending on the severity * the output with an ANSI escape sequence color code depending on the severity
* of the message. * of the message.
*/ */
class ansicolor_sink : public sink class ansicolor_sink SPDLOG_FINAL: public sink
{ {
public: public:
ansicolor_sink(sink_ptr wrapped_sink); ansicolor_sink(sink_ptr wrapped_sink);
@ -66,12 +67,14 @@ public:
protected: protected:
bool is_color_terminal_;
sink_ptr sink_; sink_ptr sink_;
std::map<level::level_enum, std::string> colors_; std::map<level::level_enum, std::string> colors_;
}; };
inline ansicolor_sink::ansicolor_sink(sink_ptr wrapped_sink) : sink_(wrapped_sink) inline ansicolor_sink::ansicolor_sink(sink_ptr wrapped_sink): sink_(wrapped_sink)
{ {
is_color_terminal_ = details::os::is_color_terminal();
colors_[level::trace] = cyan; colors_[level::trace] = cyan;
colors_[level::debug] = cyan; colors_[level::debug] = cyan;
colors_[level::info] = bold; colors_[level::info] = bold;
@ -83,7 +86,10 @@ inline ansicolor_sink::ansicolor_sink(sink_ptr wrapped_sink) : sink_(wrapped_sin
inline void ansicolor_sink::log(const details::log_msg& msg) inline void ansicolor_sink::log(const details::log_msg& msg)
{ {
// Wrap the originally formatted message in color codes // Wrap the originally formatted message in color codes.
// If color is not supported in the terminal, log as is instead.
if (is_color_terminal_)
{
const std::string& prefix = colors_[msg.level]; const std::string& prefix = colors_[msg.level];
const std::string& s = msg.formatted.str(); const std::string& s = msg.formatted.str();
const std::string& suffix = reset; const std::string& suffix = reset;
@ -94,6 +100,11 @@ inline void ansicolor_sink::log(const details::log_msg& msg)
m.thread_id = msg.thread_id; m.thread_id = msg.thread_id;
m.formatted << prefix << s << suffix; m.formatted << prefix << s << suffix;
sink_->log(m); sink_->log(m);
}
else
{
sink_->log(msg);
}
} }
inline void ansicolor_sink::flush() inline void ansicolor_sink::flush()

@ -5,8 +5,8 @@
#pragma once #pragma once
// //
// base sink templated over a mutex (either dummy or realy) // base sink templated over a mutex (either dummy or real)
// concrete implementation should only overrid the _sink_it method. // concrete implementation should only override the _sink_it method.
// all locking is taken care of here so no locking needed by the implementers.. // all locking is taken care of here so no locking needed by the implementers..
// //
@ -31,7 +31,7 @@ public:
base_sink(const base_sink&) = delete; base_sink(const base_sink&) = delete;
base_sink& operator=(const base_sink&) = delete; base_sink& operator=(const base_sink&) = delete;
void log(const details::log_msg& msg) override void log(const details::log_msg& msg) SPDLOG_FINAL override
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_sink_it(msg); _sink_it(msg);

@ -26,7 +26,7 @@ namespace sinks
* Trivial file sink with single file as target * Trivial file sink with single file as target
*/ */
template<class Mutex> template<class Mutex>
class simple_file_sink : public base_sink < Mutex > class simple_file_sink SPDLOG_FINAL : public base_sink < Mutex >
{ {
public: public:
explicit simple_file_sink(const filename_t &filename, bool truncate = false):_force_flush(false) explicit simple_file_sink(const filename_t &filename, bool truncate = false):_force_flush(false)
@ -61,7 +61,7 @@ typedef simple_file_sink<details::null_mutex> simple_file_sink_st;
* Rotating file sink based on size * Rotating file sink based on size
*/ */
template<class Mutex> template<class Mutex>
class rotating_file_sink : public base_sink < Mutex > class rotating_file_sink SPDLOG_FINAL : public base_sink < Mutex >
{ {
public: public:
rotating_file_sink(const filename_t &base_filename, rotating_file_sink(const filename_t &base_filename,
@ -177,7 +177,7 @@ struct dateonly_daily_file_name_calculator
* Rotating file sink based on date. rotates at midnight * Rotating file sink based on date. rotates at midnight
*/ */
template<class Mutex, class FileNameCalc = default_daily_file_name_calculator> template<class Mutex, class FileNameCalc = default_daily_file_name_calculator>
class daily_file_sink :public base_sink < Mutex > class daily_file_sink SPDLOG_FINAL :public base_sink < Mutex >
{ {
public: public:
//create daily file sink which rotates on given time //create daily file sink which rotates on given time

@ -18,7 +18,7 @@ namespace sinks
{ {
template <class Mutex> template <class Mutex>
class stdout_sink: public base_sink<Mutex> class stdout_sink SPDLOG_FINAL : public base_sink<Mutex>
{ {
using MyType = stdout_sink<Mutex>; using MyType = stdout_sink<Mutex>;
public: public:
@ -47,7 +47,7 @@ typedef stdout_sink<std::mutex> stdout_sink_mt;
template <class Mutex> template <class Mutex>
class stderr_sink: public base_sink<Mutex> class stderr_sink SPDLOG_FINAL : public base_sink<Mutex>
{ {
using MyType = stderr_sink<Mutex>; using MyType = stderr_sink<Mutex>;
public: public:

@ -101,8 +101,22 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to enable wchar_t support (convert to utf8)
//
// #define SPDLOG_WCHAR_TO_UTF8_SUPPORT
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Uncomment to prevent child processes from inheriting log file descriptors // Uncomment to prevent child processes from inheriting log file descriptors
// //
// #define SPDLOG_PREVENT_CHILD_FD // #define SPDLOG_PREVENT_CHILD_FD
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to mark some types as final, allowing more optimizations in release
// mode with recent compilers. See GCC's documentation for -Wsuggest-final-types
// for instance.
//
// #define SPDLOG_FINAL final
///////////////////////////////////////////////////////////////////////////////

@ -10,7 +10,7 @@ find_package(Threads)
add_library(catch INTERFACE) add_library(catch INTERFACE)
target_include_directories(catch INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(catch INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
file(GLOB catch_tests LIST_DIRECTORIES false RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) file(GLOB catch_tests LIST_DIRECTORIES false RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp *.h *.hpp)
add_executable(catch_tests ${catch_tests}) add_executable(catch_tests ${catch_tests})
target_link_libraries(catch_tests spdlog ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(catch_tests spdlog ${CMAKE_THREAD_LIBS_INIT})

Loading…
Cancel
Save