Upgraded spdlog to v1.11.0

This commit is contained in:
Bartek Kryza
2023-06-03 18:00:54 +02:00
parent a78839eecf
commit 12f129a6fe
72 changed files with 6797 additions and 4117 deletions

View File

@@ -16,6 +16,7 @@
# include <mutex>
# include <string>
# include <thread>
# include <type_traits>
# if !defined(SPDLOG_ANDROID_RETRIES)
# define SPDLOG_ANDROID_RETRIES 2
@@ -25,9 +26,10 @@ namespace spdlog {
namespace sinks {
/*
* Android sink (logging using __android_log_write)
* Android sink
* (logging using __android_log_write or __android_log_buf_write depending on the specified BufferID)
*/
template<typename Mutex>
template<typename Mutex, int BufferID = log_id::LOG_ID_MAIN>
class android_sink final : public base_sink<Mutex>
{
public:
@@ -53,24 +55,39 @@ protected:
const char *msg_output = formatted.data();
// See system/core/liblog/logger_write.c for explanation of return value
int ret = __android_log_write(priority, tag_.c_str(), msg_output);
int ret = android_log(priority, tag_.c_str(), msg_output);
int retry_count = 0;
while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES))
{
details::os::sleep_for_millis(5);
ret = __android_log_write(priority, tag_.c_str(), msg_output);
ret = android_log(priority, tag_.c_str(), msg_output);
retry_count++;
}
if (ret < 0)
{
throw_spdlog_ex("__android_log_write() failed", ret);
throw_spdlog_ex("logging to Android failed", ret);
}
}
void flush_() override {}
private:
// There might be liblog versions used, that do not support __android_log_buf_write. So we only compile and link against
// __android_log_buf_write, if user explicitely provides a non-default log buffer. Otherwise, when using the default log buffer, always
// log via __android_log_write.
template<int ID = BufferID>
typename std::enable_if<ID == static_cast<int>(log_id::LOG_ID_MAIN), int>::type android_log(int prio, const char *tag, const char *text)
{
return __android_log_write(prio, tag, text);
}
template<int ID = BufferID>
typename std::enable_if<ID != static_cast<int>(log_id::LOG_ID_MAIN), int>::type android_log(int prio, const char *tag, const char *text)
{
return __android_log_buf_write(ID, prio, tag, text);
}
static android_LogPriority convert_to_android_(spdlog::level::level_enum level)
{
switch (level)
@@ -98,6 +115,12 @@ private:
using android_sink_mt = android_sink<std::mutex>;
using android_sink_st = android_sink<details::null_mutex>;
template<int BufferId = log_id::LOG_ID_MAIN>
using android_sink_buf_mt = android_sink<std::mutex, BufferId>;
template<int BufferId = log_id::LOG_ID_MAIN>
using android_sink_buf_st = android_sink<details::null_mutex, BufferId>;
} // namespace sinks
// Create and register android syslog logger

View File

@@ -34,7 +34,7 @@ template<typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color(level::level_enum color_level, string_view_t color)
{
std::lock_guard<mutex_t> lock(mutex_);
colors_[color_level] = to_string_(color);
colors_[static_cast<size_t>(color_level)] = to_string_(color);
}
template<typename ConsoleMutex>
@@ -52,7 +52,7 @@ SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::log(const details::log_msg &msg
// before color range
print_range_(formatted, 0, msg.color_range_start);
// in color range
print_ccode_(colors_[msg.level]);
print_ccode_(colors_[static_cast<size_t>(msg.level)]);
print_range_(formatted, msg.color_range_start, msg.color_range_end);
print_ccode_(reset);
// after color range

View File

@@ -16,7 +16,7 @@
namespace spdlog {
namespace sinks {
template<typename Mutex>
class base_sink : public sink
class SPDLOG_API base_sink : public sink
{
public:
base_sink();
@@ -37,7 +37,7 @@ public:
protected:
// sink formatter
std::unique_ptr<spdlog::formatter> formatter_;
mutable Mutex mutex_;
Mutex mutex_;
virtual void sink_it_(const details::log_msg &msg) = 0;
virtual void flush_() = 0;

View File

@@ -14,7 +14,8 @@ namespace spdlog {
namespace sinks {
template<typename Mutex>
SPDLOG_INLINE basic_file_sink<Mutex>::basic_file_sink(const filename_t &filename, bool truncate)
SPDLOG_INLINE basic_file_sink<Mutex>::basic_file_sink(const filename_t &filename, bool truncate, const file_event_handlers &event_handlers)
: file_helper_{event_handlers}
{
file_helper_.open(filename, truncate);
}

View File

@@ -20,7 +20,7 @@ template<typename Mutex>
class basic_file_sink final : public base_sink<Mutex>
{
public:
explicit basic_file_sink(const filename_t &filename, bool truncate = false);
explicit basic_file_sink(const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {});
const filename_t &filename() const;
protected:
@@ -40,15 +40,17 @@ using basic_file_sink_st = basic_file_sink<details::null_mutex>;
// factory functions
//
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false)
inline std::shared_ptr<logger> basic_logger_mt(
const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::basic_file_sink_mt>(logger_name, filename, truncate);
return Factory::template create<sinks::basic_file_sink_mt>(logger_name, filename, truncate, event_handlers);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false)
inline std::shared_ptr<logger> basic_logger_st(
const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::basic_file_sink_st>(logger_name, filename, truncate);
return Factory::template create<sinks::basic_file_sink_st>(logger_name, filename, truncate, event_handlers);
}
} // namespace spdlog

View File

@@ -32,8 +32,8 @@ struct daily_filename_calculator
{
filename_t basename, ext;
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
return fmt::format(
SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, ext);
return fmt_lib::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}")), basename, now_tm.tm_year + 1900,
now_tm.tm_mon + 1, now_tm.tm_mday, ext);
}
};
@@ -48,14 +48,65 @@ struct daily_filename_format_calculator
{
static filename_t calc_filename(const filename_t &filename, const tm &now_tm)
{
// generate fmt datetime format string, e.g. {:%Y-%m-%d}.
filename_t fmt_filename = fmt::format(SPDLOG_FILENAME_T("{{:{}}}"), filename);
#if defined(_MSC_VER) && defined(SPDLOG_WCHAR_FILENAMES) // for some reason msvc doesnt allow fmt::runtime(..) with wchar here
return fmt::format(fmt_filename, now_tm);
#ifdef SPDLOG_USE_STD_FORMAT
// adapted from fmtlib: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/chrono.h#L522-L546
filename_t tm_format;
tm_format.append(filename);
// By appending an extra space we can distinguish an empty result that
// indicates insufficient buffer size from a guaranteed non-empty result
// https://github.com/fmtlib/fmt/issues/2238
tm_format.push_back(' ');
const size_t MIN_SIZE = 10;
filename_t buf;
buf.resize(MIN_SIZE);
for (;;)
{
size_t count = strftime(buf.data(), buf.size(), tm_format.c_str(), &now_tm);
if (count != 0)
{
// Remove the extra space.
buf.resize(count - 1);
break;
}
buf.resize(buf.size() * 2);
}
return buf;
#else
// generate fmt datetime format string, e.g. {:%Y-%m-%d}.
filename_t fmt_filename = fmt::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{{:{}}}")), filename);
// MSVC doesn't allow fmt::runtime(..) with wchar, with fmtlib versions < 9.1.x
# if defined(_MSC_VER) && defined(SPDLOG_WCHAR_FILENAMES) && FMT_VERSION < 90101
return fmt::format(fmt_filename, now_tm);
# else
return fmt::format(SPDLOG_FMT_RUNTIME(fmt_filename), now_tm);
# endif
#endif
}
private:
#if defined __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
static size_t strftime(char *str, size_t count, const char *format, const std::tm *time)
{
return std::strftime(str, count, format, time);
}
static size_t strftime(wchar_t *str, size_t count, const wchar_t *format, const std::tm *time)
{
return std::wcsftime(str, count, format, time);
}
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif
};
/*
@@ -68,10 +119,12 @@ class daily_file_sink final : public base_sink<Mutex>
{
public:
// create daily file sink which rotates on given time
daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0)
daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0,
const file_event_handlers &event_handlers = {})
: base_filename_(std::move(base_filename))
, rotation_h_(rotation_hour)
, rotation_m_(rotation_minute)
, file_helper_{event_handlers}
, truncate_(truncate)
, max_files_(max_files)
, filenames_q_()
@@ -213,30 +266,32 @@ using daily_file_format_sink_st = daily_file_sink<details::null_mutex, daily_fil
// factory functions
//
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_mt(
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
inline std::shared_ptr<logger> daily_logger_mt(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0,
bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files);
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files, event_handlers);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_format_mt(
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
inline std::shared_ptr<logger> daily_logger_format_mt(const std::string &logger_name, const filename_t &filename, int hour = 0,
int minute = 0, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::daily_file_format_sink_mt>(logger_name, filename, hour, minute, truncate, max_files);
return Factory::template create<sinks::daily_file_format_sink_mt>(
logger_name, filename, hour, minute, truncate, max_files, event_handlers);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_st(
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
inline std::shared_ptr<logger> daily_logger_st(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0,
bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files);
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files, event_handlers);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_format_st(
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
inline std::shared_ptr<logger> daily_logger_format_st(const std::string &logger_name, const filename_t &filename, int hour = 0,
int minute = 0, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::daily_file_format_sink_st>(logger_name, filename, hour, minute, truncate, max_files);
return Factory::template create<sinks::daily_file_format_sink_st>(
logger_name, filename, hour, minute, truncate, max_files, event_handlers);
}
} // namespace spdlog

View File

@@ -57,20 +57,20 @@ public:
protected:
void sink_it_(const details::log_msg &msg) override
{
for (auto &sink : sinks_)
for (auto &sub_sink : sinks_)
{
if (sink->should_log(msg.level))
if (sub_sink->should_log(msg.level))
{
sink->log(msg);
sub_sink->log(msg);
}
}
}
void flush_() override
{
for (auto &sink : sinks_)
for (auto &sub_sink : sinks_)
{
sink->flush();
sub_sink->flush();
}
}
@@ -82,9 +82,9 @@ protected:
void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter) override
{
base_sink<Mutex>::formatter_ = std::move(sink_formatter);
for (auto &sink : sinks_)
for (auto &sub_sink : sinks_)
{
sink->set_formatter(base_sink<Mutex>::formatter_->clone());
sub_sink->set_formatter(base_sink<Mutex>::formatter_->clone());
}
}
std::vector<std::shared_ptr<sink>> sinks_;

View File

@@ -31,7 +31,7 @@ struct hourly_filename_calculator
{
filename_t basename, ext;
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
return fmt::format(SPDLOG_FILENAME_T("{}_{:04d}{:02d}{:02d}_{:02d}{}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1,
return fmt_lib::format(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}{}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1,
now_tm.tm_mday, now_tm.tm_hour, ext);
}
};
@@ -46,8 +46,10 @@ class hourly_file_sink final : public base_sink<Mutex>
{
public:
// create hourly file sink which rotates on given time
hourly_file_sink(filename_t base_filename, bool truncate = false, uint16_t max_files = 0)
hourly_file_sink(
filename_t base_filename, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {})
: base_filename_(std::move(base_filename))
, file_helper_{event_handlers}
, truncate_(truncate)
, max_files_(max_files)
, filenames_q_()
@@ -55,6 +57,7 @@ public:
auto now = log_clock::now();
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));
file_helper_.open(filename, truncate_);
remove_init_file_ = file_helper_.size() == 0;
rotation_tp_ = next_rotation_tp_();
if (max_files_ > 0)
@@ -76,10 +79,16 @@ protected:
bool should_rotate = time >= rotation_tp_;
if (should_rotate)
{
if (remove_init_file_)
{
file_helper_.close();
details::os::remove(file_helper_.filename());
}
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time));
file_helper_.open(filename, truncate_);
rotation_tp_ = next_rotation_tp_();
}
remove_init_file_ = false;
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
file_helper_.write(formatted);
@@ -168,6 +177,7 @@ private:
bool truncate_;
uint16_t max_files_;
details::circular_q<filename_t> filenames_q_;
bool remove_init_file_;
};
using hourly_file_sink_mt = hourly_file_sink<std::mutex>;
@@ -179,16 +189,16 @@ using hourly_file_sink_st = hourly_file_sink<details::null_mutex>;
// factory functions
//
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> hourly_logger_mt(
const std::string &logger_name, const filename_t &filename, bool truncate = false, uint16_t max_files = 0)
inline std::shared_ptr<logger> hourly_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false,
uint16_t max_files = 0, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::hourly_file_sink_mt>(logger_name, filename, truncate, max_files);
return Factory::template create<sinks::hourly_file_sink_mt>(logger_name, filename, truncate, max_files, event_handlers);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> hourly_logger_st(
const std::string &logger_name, const filename_t &filename, bool truncate = false, uint16_t max_files = 0)
inline std::shared_ptr<logger> hourly_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false,
uint16_t max_files = 0, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::hourly_file_sink_st>(logger_name, filename, truncate, max_files);
return Factory::template create<sinks::hourly_file_sink_st>(logger_name, filename, truncate, max_files, event_handlers);
}
} // namespace spdlog

View File

@@ -30,16 +30,26 @@ class mongo_sink : public base_sink<Mutex>
{
public:
mongo_sink(const std::string &db_name, const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017")
try : mongo_sink(std::make_shared<mongocxx::instance>(), db_name, collection_name, uri)
{}
catch (const std::exception &e)
{
throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what()));
}
mongo_sink(std::shared_ptr<mongocxx::instance> instance, const std::string &db_name, const std::string &collection_name,
const std::string &uri = "mongodb://localhost:27017")
: instance_(std::move(instance))
, db_name_(db_name)
, coll_name_(collection_name)
{
try
{
client_ = spdlog::details::make_unique<mongocxx::client>(mongocxx::uri{uri});
db_name_ = db_name;
coll_name_ = collection_name;
}
catch (const std::exception)
catch (const std::exception &e)
{
throw spdlog_ex("Error opening database");
throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what()));
}
}
@@ -57,8 +67,8 @@ protected:
if (client_ != nullptr)
{
auto doc = document{} << "timestamp" << bsoncxx::types::b_date(msg.time) << "level" << level::to_string_view(msg.level).data()
<< "message" << std::string(msg.payload.begin(), msg.payload.end()) << "logger_name"
<< std::string(msg.logger_name.begin(), msg.logger_name.end()) << "thread_id"
<< "level_num" << msg.level << "message" << std::string(msg.payload.begin(), msg.payload.end())
<< "logger_name" << std::string(msg.logger_name.begin(), msg.logger_name.end()) << "thread_id"
<< static_cast<int>(msg.thread_id) << finalize;
client_->database(db_name_).collection(coll_name_).insert_one(doc.view());
}
@@ -67,12 +77,11 @@ protected:
void flush_() override {}
private:
static mongocxx::instance instance_;
std::shared_ptr<mongocxx::instance> instance_;
std::string db_name_;
std::string coll_name_;
std::unique_ptr<mongocxx::client> client_ = nullptr;
};
mongocxx::instance mongo_sink<std::mutex>::instance_{};
#include "spdlog/details/null_mutex.h"
#include <mutex>

View File

@@ -1,8 +1,9 @@
// Copyright(c) 2016 Alexander Dalshov.
// Copyright(c) 2016 Alexander Dalshov & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#if defined(_WIN32)
# include <spdlog/details/null_mutex.h>
@@ -13,6 +14,7 @@
// Avoid including windows.h (https://stackoverflow.com/a/30741042)
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char *lpOutputString);
extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
namespace spdlog {
namespace sinks {
@@ -24,16 +26,25 @@ class msvc_sink : public base_sink<Mutex>
{
public:
msvc_sink() = default;
msvc_sink(bool check_ebugger_present)
: check_debbugger_present_{check_ebugger_present} {};
protected:
void sink_it_(const details::log_msg &msg) override
{
if (check_debbugger_present_ && !IsDebuggerPresent())
{
return;
}
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
OutputDebugStringA(fmt::to_string(formatted).c_str());
formatted.push_back('\0'); // add a null terminator for OutputDebugStringA
OutputDebugStringA(formatted.data());
}
void flush_() override {}
bool check_debbugger_present_ = true;
};
using msvc_sink_mt = msvc_sink<std::mutex>;

View File

@@ -21,29 +21,36 @@
//
namespace spdlog {
namespace sinks {
template <typename Mutex> class qt_sink : public base_sink<Mutex> {
template<typename Mutex>
class qt_sink : public base_sink<Mutex>
{
public:
qt_sink(QObject *qt_object = nullptr, const std::string &meta_method = "") {
qt_object_ = qt_object;
meta_method_ = meta_method;
}
qt_sink(QObject *qt_object, const std::string &meta_method)
{
qt_object_ = qt_object;
meta_method_ = meta_method;
}
~qt_sink() { flush_(); }
~qt_sink()
{
flush_();
}
protected:
void sink_it_(const details::log_msg &msg) override {
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
string_view_t str = string_view_t(formatted.data(), formatted.size());
QMetaObject::invokeMethod(qt_object_, meta_method_.c_str(), Qt::AutoConnection,
Q_ARG(QString, QString::fromUtf8(str.data(), static_cast<int>(str.size())).trimmed()));
}
void sink_it_(const details::log_msg &msg) override
{
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
string_view_t str = string_view_t(formatted.data(), formatted.size());
QMetaObject::invokeMethod(qt_object_, meta_method_.c_str(), Qt::AutoConnection,
Q_ARG(QString, QString::fromUtf8(str.data(), static_cast<int>(str.size())).trimmed()));
}
void flush_() override {}
void flush_() override {}
private:
QObject *qt_object_ = nullptr;
std::string meta_method_;
QObject *qt_object_ = nullptr;
std::string meta_method_;
};
#include "spdlog/details/null_mutex.h"
@@ -55,39 +62,41 @@ using qt_sink_st = qt_sink<spdlog::details::null_mutex>;
//
// Factory functions
//
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger>
qt_logger_mt(const std::string &logger_name, QTextEdit* qt_object, const std::string &meta_method = "append") {
return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger>
qt_logger_st(const std::string &logger_name, QTextEdit* qt_object, const std::string &meta_method = "append") {
return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger>
qt_logger_mt(const std::string &logger_name, QPlainTextEdit* qt_object , const std::string &meta_method = "appendPlainText") {
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_mt(const std::string &logger_name, QTextEdit *qt_object, const std::string &meta_method = "append")
{
return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger>
qt_logger_st(const std::string &logger_name, QPlainTextEdit* qt_object, const std::string &meta_method = "appendPlainText") {
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_st(const std::string &logger_name, QTextEdit *qt_object, const std::string &meta_method = "append")
{
return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger>
qt_logger_mt(const std::string &logger_name, QObject* qt_object, const std::string &meta_method) {
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_mt(
const std::string &logger_name, QPlainTextEdit *qt_object, const std::string &meta_method = "appendPlainText")
{
return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger>
qt_logger_st(const std::string &logger_name, QObject* qt_object, const std::string &meta_method) {
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_st(
const std::string &logger_name, QPlainTextEdit *qt_object, const std::string &meta_method = "appendPlainText")
{
return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_mt(const std::string &logger_name, QObject *qt_object, const std::string &meta_method)
{
return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_st(const std::string &logger_name, QObject *qt_object, const std::string &meta_method)
{
return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method);
}
} // namespace spdlog

View File

@@ -50,7 +50,7 @@ public:
{
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(q_.at(i), formatted);
ret.push_back(fmt::to_string(formatted));
ret.push_back(std::move(SPDLOG_BUF_TO_STRING(formatted)));
}
return ret;
}

View File

@@ -25,16 +25,27 @@ namespace sinks {
template<typename Mutex>
SPDLOG_INLINE rotating_file_sink<Mutex>::rotating_file_sink(
filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open)
filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open, const file_event_handlers &event_handlers)
: base_filename_(std::move(base_filename))
, max_size_(max_size)
, max_files_(max_files)
, file_helper_{event_handlers}
{
if (max_size == 0)
{
throw_spdlog_ex("rotating sink constructor: max_size arg cannot be zero");
}
if (max_files > 200000)
{
throw_spdlog_ex("rotating sink constructor: max_files arg cannot exceed 200000");
}
file_helper_.open(calc_filename(base_filename_, 0));
current_size_ = file_helper_.size(); // expensive. called only once
if (rotate_on_open && current_size_ > 0)
{
rotate_();
current_size_ = 0;
}
}
@@ -50,7 +61,7 @@ SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::calc_filename(const filename
filename_t basename, ext;
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
return fmt::format(SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext);
return fmt_lib::format(SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext);
}
template<typename Mutex>
@@ -65,13 +76,22 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::sink_it_(const details::log_msg &m
{
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
current_size_ += formatted.size();
if (current_size_ > max_size_)
auto new_size = current_size_ + formatted.size();
// rotate if the new estimated file size exceeds max size.
// rotate only if the real size > 0 to better deal with full disk (see issue #2261).
// we only check the real size when new_size > max_size_ because it is relatively expensive.
if (new_size > max_size_)
{
rotate_();
current_size_ = formatted.size();
file_helper_.flush();
if (file_helper_.size() > 0)
{
rotate_();
new_size = formatted.size();
}
}
file_helper_.write(formatted);
current_size_ = new_size;
}
template<typename Mutex>
@@ -90,6 +110,7 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::rotate_()
{
using details::os::filename_to_str;
using details::os::path_exists;
file_helper_.close();
for (auto i = max_files_; i > 0; --i)
{

View File

@@ -22,7 +22,8 @@ template<typename Mutex>
class rotating_file_sink final : public base_sink<Mutex>
{
public:
rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false);
rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false,
const file_event_handlers &event_handlers = {});
static filename_t calc_filename(const filename_t &filename, std::size_t index);
filename_t filename();
@@ -59,17 +60,19 @@ using rotating_file_sink_st = rotating_file_sink<details::null_mutex>;
//
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> rotating_logger_mt(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files, bool rotate_on_open = false)
inline std::shared_ptr<logger> rotating_logger_mt(const std::string &logger_name, const filename_t &filename, size_t max_file_size,
size_t max_files, bool rotate_on_open = false, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files, rotate_on_open);
return Factory::template create<sinks::rotating_file_sink_mt>(
logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> rotating_logger_st(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files, bool rotate_on_open = false)
inline std::shared_ptr<logger> rotating_logger_st(const std::string &logger_name, const filename_t &filename, size_t max_file_size,
size_t max_files, bool rotate_on_open = false, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files, rotate_on_open);
return Factory::template create<sinks::rotating_file_sink_st>(
logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers);
}
} // namespace spdlog

View File

@@ -16,7 +16,7 @@
// so instead we use ::FileWrite
# include <spdlog/details/windows_include.h>
# ifndef _USING_V110_SDK71_ // fileapi.h doesnt exist in winxp
# ifndef _USING_V110_SDK71_ // fileapi.h doesn't exist in winxp
# include <fileapi.h> // WriteFile (..)
# endif
@@ -37,7 +37,7 @@ SPDLOG_INLINE stdout_sink_base<ConsoleMutex>::stdout_sink_base(FILE *file)
#ifdef _WIN32
// get windows handle from the FILE* object
handle_ = (HANDLE)::_get_osfhandle(::_fileno(file_));
handle_ = reinterpret_cast<HANDLE>(::_get_osfhandle(::_fileno(file_)));
// don't throw to support cases where no console is attached,
// and let the log method to do nothing if (handle_ == INVALID_HANDLE_VALUE).
@@ -60,7 +60,7 @@ SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::log(const details::log_msg &m
std::lock_guard<mutex_t> lock(mutex_);
memory_buf_t formatted;
formatter_->format(msg, formatted);
::fflush(file_); // flush in case there is somthing in this file_ already
::fflush(file_); // flush in case there is something in this file_ already
auto size = static_cast<DWORD>(formatted.size());
DWORD bytes_written = 0;
bool ok = ::WriteFile(handle_, formatted.data(), size, &bytes_written, nullptr) != 0;

View File

@@ -18,16 +18,15 @@ namespace sinks {
/**
* Sink that write to systemd journal using the `sd_journal_send()` library call.
*
* Locking is not needed, as `sd_journal_send()` itself is thread-safe.
*/
template<typename Mutex>
class systemd_sink : public base_sink<Mutex>
{
public:
//
systemd_sink()
: syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG,
systemd_sink(std::string ident = "", bool enable_formatting = false)
: ident_{std::move(ident)}
, enable_formatting_{enable_formatting}
, syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG,
/* spdlog::level::debug */ LOG_DEBUG,
/* spdlog::level::info */ LOG_INFO,
/* spdlog::level::warn */ LOG_WARNING,
@@ -42,31 +41,46 @@ public:
systemd_sink &operator=(const systemd_sink &) = delete;
protected:
const std::string ident_;
bool enable_formatting_ = false;
using levels_array = std::array<int, 7>;
levels_array syslog_levels_;
void sink_it_(const details::log_msg &msg) override
{
int err;
string_view_t payload;
memory_buf_t formatted;
if (enable_formatting_)
{
base_sink<Mutex>::formatter_->format(msg, formatted);
payload = string_view_t(formatted.data(), formatted.size());
}
else
{
payload = msg.payload;
}
size_t length = msg.payload.size();
size_t length = payload.size();
// limit to max int
if (length > static_cast<size_t>(std::numeric_limits<int>::max()))
{
length = static_cast<size_t>(std::numeric_limits<int>::max());
}
const string_view_t syslog_identifier = ident_.empty() ? msg.logger_name : ident_;
// Do not send source location if not available
if (msg.source.empty())
{
// Note: function call inside '()' to avoid macro expansion
err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level),
"SYSLOG_IDENTIFIER=%.*s", static_cast<int>(msg.logger_name.size()), msg.logger_name.data(), nullptr);
err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), payload.data(), "PRIORITY=%d", syslog_level(msg.level),
"SYSLOG_IDENTIFIER=%.*s", static_cast<int>(syslog_identifier.size()), syslog_identifier.data(), nullptr);
}
else
{
err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level),
"SYSLOG_IDENTIFIER=%.*s", static_cast<int>(msg.logger_name.size()), msg.logger_name.data(), "CODE_FILE=%s",
err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), payload.data(), "PRIORITY=%d", syslog_level(msg.level),
"SYSLOG_IDENTIFIER=%.*s", static_cast<int>(syslog_identifier.size()), syslog_identifier.data(), "CODE_FILE=%s",
msg.source.filename, "CODE_LINE=%d", msg.source.line, "CODE_FUNC=%s", msg.source.funcname, nullptr);
}
@@ -90,14 +104,16 @@ using systemd_sink_st = systemd_sink<details::null_mutex>;
// Create and register a syslog logger
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> systemd_logger_mt(const std::string &logger_name)
inline std::shared_ptr<logger> systemd_logger_mt(
const std::string &logger_name, const std::string &ident = "", bool enable_formatting = false)
{
return Factory::template create<sinks::systemd_sink_mt>(logger_name);
return Factory::template create<sinks::systemd_sink_mt>(logger_name, ident, enable_formatting);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> systemd_logger_st(const std::string &logger_name)
inline std::shared_ptr<logger> systemd_logger_st(
const std::string &logger_name, const std::string &ident = "", bool enable_formatting = false)
{
return Factory::template create<sinks::systemd_sink_st>(logger_name);
return Factory::template create<sinks::systemd_sink_st>(logger_name, ident, enable_formatting);
}
} // namespace spdlog

74
thirdparty/spdlog/sinks/udp_sink.h vendored Normal file
View File

@@ -0,0 +1,74 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/common.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/null_mutex.h>
#ifdef _WIN32
# include <spdlog/details/udp_client-windows.h>
#else
# include <spdlog/details/udp_client.h>
#endif
#include <mutex>
#include <string>
#include <chrono>
#include <functional>
// Simple udp client sink
// Sends formatted log via udp
namespace spdlog {
namespace sinks {
struct udp_sink_config
{
std::string server_host;
uint16_t server_port;
udp_sink_config(std::string host, uint16_t port)
: server_host{std::move(host)}
, server_port{port}
{}
};
template<typename Mutex>
class udp_sink : public spdlog::sinks::base_sink<Mutex>
{
public:
// host can be hostname or ip address
explicit udp_sink(udp_sink_config sink_config)
: client_{sink_config.server_host, sink_config.server_port}
{}
~udp_sink() override = default;
protected:
void sink_it_(const spdlog::details::log_msg &msg) override
{
spdlog::memory_buf_t formatted;
spdlog::sinks::base_sink<Mutex>::formatter_->format(msg, formatted);
client_.send(formatted.data(), formatted.size());
}
void flush_() override {}
details::udp_client client_;
};
using udp_sink_mt = udp_sink<std::mutex>;
using udp_sink_st = udp_sink<spdlog::details::null_mutex>;
} // namespace sinks
//
// factory functions
//
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> udp_logger_mt(const std::string &logger_name, sinks::udp_sink_config skin_config)
{
return Factory::template create<sinks::udp_sink_mt>(logger_name, skin_config);
}
} // namespace spdlog

View File

@@ -47,6 +47,24 @@ namespace win_eventlog {
namespace internal {
struct local_alloc_t
{
HLOCAL hlocal_;
SPDLOG_CONSTEXPR local_alloc_t() SPDLOG_NOEXCEPT : hlocal_(nullptr) {}
local_alloc_t(local_alloc_t const &) = delete;
local_alloc_t &operator=(local_alloc_t const &) = delete;
~local_alloc_t() SPDLOG_NOEXCEPT
{
if (hlocal_)
{
LocalFree(hlocal_);
}
}
};
/** Windows error */
struct win32_error : public spdlog_ex
{
@@ -55,22 +73,17 @@ struct win32_error : public spdlog_ex
{
std::string system_message;
LPSTR format_message_result{};
local_alloc_t format_message_result{};
auto format_message_succeeded =
::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&format_message_result, 0, nullptr);
error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&format_message_result.hlocal_, 0, nullptr);
if (format_message_succeeded && format_message_result)
if (format_message_succeeded && format_message_result.hlocal_)
{
system_message = fmt::format(" ({})", format_message_result);
system_message = fmt_lib::format(" ({})", (LPSTR)format_message_result.hlocal_);
}
if (format_message_result)
{
LocalFree((HLOCAL)format_message_result);
}
return fmt::format("{}: {}{}", user_message, error_code, system_message);
return fmt_lib::format("{}: {}{}", user_message, error_code, system_message);
}
explicit win32_error(std::string const &func_name, DWORD error = GetLastError())
@@ -228,12 +241,12 @@ protected:
details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), buf);
LPCWSTR lp_wstr = buf.data();
succeeded = ::ReportEventW(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_,
current_user_sid_.as_sid(), 1, 0, &lp_wstr, nullptr);
succeeded = static_cast<bool>(::ReportEventW(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_,
current_user_sid_.as_sid(), 1, 0, &lp_wstr, nullptr));
#else
LPCSTR lp_str = formatted.data();
succeeded = ::ReportEventA(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_,
current_user_sid_.as_sid(), 1, 0, &lp_str, nullptr);
succeeded = static_cast<bool>(::ReportEventA(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_,
current_user_sid_.as_sid(), 1, 0, &lp_str, nullptr));
#endif
if (!succeeded)

View File

@@ -45,7 +45,7 @@ template<typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color(level::level_enum level, std::uint16_t color)
{
std::lock_guard<mutex_t> lock(mutex_);
colors_[level] = color;
colors_[static_cast<size_t>(level)] = color;
}
template<typename ConsoleMutex>
@@ -66,7 +66,7 @@ void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::log(const details::log_msg &msg)
// before color range
print_range_(formatted, 0, msg.color_range_start);
// in color range
auto orig_attribs = static_cast<WORD>(set_foreground_color_(colors_[msg.level]));
auto orig_attribs = static_cast<WORD>(set_foreground_color_(colors_[static_cast<size_t>(msg.level)]));
print_range_(formatted, msg.color_range_start, msg.color_range_end);
// reset to orig colors
::SetConsoleTextAttribute(static_cast<HANDLE>(out_handle_), orig_attribs);