update spdlog (it still dont work), fix 6.3(1)

This commit is contained in:
Gray
2024-06-10 16:30:29 -04:00
parent dd2bbfacda
commit bab7c30669
107 changed files with 10351 additions and 9620 deletions

View File

@@ -5,50 +5,45 @@
#ifdef __ANDROID__
# include <spdlog/details/fmt_helper.h>
# include <spdlog/details/null_mutex.h>
# include <spdlog/details/os.h>
# include <spdlog/sinks/base_sink.h>
# include <spdlog/details/synchronous_factory.h>
#include <spdlog/details/fmt_helper.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/os.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/sinks/base_sink.h>
# include <android/log.h>
# include <chrono>
# include <mutex>
# include <string>
# include <thread>
# include <type_traits>
#include <android/log.h>
#include <chrono>
#include <mutex>
#include <string>
#include <thread>
#include <type_traits>
# if !defined(SPDLOG_ANDROID_RETRIES)
# define SPDLOG_ANDROID_RETRIES 2
# endif
#if !defined(SPDLOG_ANDROID_RETRIES)
#define SPDLOG_ANDROID_RETRIES 2
#endif
namespace spdlog {
namespace sinks {
/*
* Android sink
* (logging using __android_log_write or __android_log_buf_write depending on the specified BufferID)
* (logging using __android_log_write or __android_log_buf_write depending on the specified
* BufferID)
*/
template<typename Mutex, int BufferID = log_id::LOG_ID_MAIN>
class android_sink final : public base_sink<Mutex>
{
template <typename Mutex, int BufferID = log_id::LOG_ID_MAIN>
class android_sink final : public base_sink<Mutex> {
public:
explicit android_sink(std::string tag = "spdlog", bool use_raw_msg = false)
: tag_(std::move(tag))
, use_raw_msg_(use_raw_msg)
{}
: tag_(std::move(tag)),
use_raw_msg_(use_raw_msg) {}
protected:
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
const android_LogPriority priority = convert_to_android_(msg.level);
memory_buf_t formatted;
if (use_raw_msg_)
{
if (use_raw_msg_) {
details::fmt_helper::append_string_view(msg.payload, formatted);
}
else
{
} else {
base_sink<Mutex>::formatter_->format(msg, formatted);
}
formatted.push_back('\0');
@@ -56,16 +51,17 @@ protected:
// See system/core/liblog/logger_write.c for explanation of return value
int ret = android_log(priority, tag_.c_str(), msg_output);
if (ret == -EPERM) {
return; // !__android_log_is_loggable
}
int retry_count = 0;
while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES))
{
while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES)) {
details::os::sleep_for_millis(5);
ret = android_log(priority, tag_.c_str(), msg_output);
retry_count++;
}
if (ret < 0)
{
if (ret < 0) {
throw_spdlog_ex("logging to Android failed", ret);
}
}
@@ -73,39 +69,38 @@ protected:
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)
{
// 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 explicitly 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)
{
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)
{
case spdlog::level::trace:
return ANDROID_LOG_VERBOSE;
case spdlog::level::debug:
return ANDROID_LOG_DEBUG;
case spdlog::level::info:
return ANDROID_LOG_INFO;
case spdlog::level::warn:
return ANDROID_LOG_WARN;
case spdlog::level::err:
return ANDROID_LOG_ERROR;
case spdlog::level::critical:
return ANDROID_LOG_FATAL;
default:
return ANDROID_LOG_DEFAULT;
static android_LogPriority convert_to_android_(spdlog::level::level_enum level) {
switch (level) {
case spdlog::level::trace:
return ANDROID_LOG_VERBOSE;
case spdlog::level::debug:
return ANDROID_LOG_DEBUG;
case spdlog::level::info:
return ANDROID_LOG_INFO;
case spdlog::level::warn:
return ANDROID_LOG_WARN;
case spdlog::level::err:
return ANDROID_LOG_ERROR;
case spdlog::level::critical:
return ANDROID_LOG_FATAL;
default:
return ANDROID_LOG_DEFAULT;
}
}
@@ -116,27 +111,27 @@ 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>
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>
template <int BufferId = log_id::LOG_ID_MAIN>
using android_sink_buf_st = android_sink<details::null_mutex, BufferId>;
} // namespace sinks
} // namespace sinks
// Create and register android syslog logger
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> android_logger_mt(const std::string &logger_name, const std::string &tag = "spdlog")
{
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> android_logger_mt(const std::string &logger_name,
const std::string &tag = "spdlog") {
return Factory::template create<sinks::android_sink_mt>(logger_name, tag);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> android_logger_st(const std::string &logger_name, const std::string &tag = "spdlog")
{
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> android_logger_st(const std::string &logger_name,
const std::string &tag = "spdlog") {
return Factory::template create<sinks::android_sink_st>(logger_name, tag);
}
} // namespace spdlog
} // namespace spdlog
#endif // __ANDROID__
#endif // __ANDROID__

View File

@@ -4,42 +4,41 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
# include <spdlog/sinks/ansicolor_sink.h>
#include <spdlog/sinks/ansicolor_sink.h>
#endif
#include <spdlog/pattern_formatter.h>
#include <spdlog/details/os.h>
#include <spdlog/pattern_formatter.h>
namespace spdlog {
namespace sinks {
template<typename ConsoleMutex>
template <typename ConsoleMutex>
SPDLOG_INLINE ansicolor_sink<ConsoleMutex>::ansicolor_sink(FILE *target_file, color_mode mode)
: target_file_(target_file)
, mutex_(ConsoleMutex::mutex())
, formatter_(details::make_unique<spdlog::pattern_formatter>())
: target_file_(target_file),
mutex_(ConsoleMutex::mutex()),
formatter_(details::make_unique<spdlog::pattern_formatter>())
{
set_color_mode(mode);
colors_[level::trace] = to_string_(white);
colors_[level::debug] = to_string_(cyan);
colors_[level::info] = to_string_(green);
colors_[level::warn] = to_string_(yellow_bold);
colors_[level::err] = to_string_(red_bold);
colors_[level::critical] = to_string_(bold_on_red);
colors_[level::off] = to_string_(reset);
colors_.at(level::trace) = to_string_(white);
colors_.at(level::debug) = to_string_(cyan);
colors_.at(level::info) = to_string_(green);
colors_.at(level::warn) = to_string_(yellow_bold);
colors_.at(level::err) = to_string_(red_bold);
colors_.at(level::critical) = to_string_(bold_on_red);
colors_.at(level::off) = to_string_(reset);
}
template<typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color(level::level_enum color_level, string_view_t color)
{
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_[static_cast<size_t>(color_level)] = to_string_(color);
colors_.at(static_cast<size_t>(color_level)) = to_string_(color);
}
template<typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::log(const details::log_msg &msg)
{
template <typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::log(const details::log_msg &msg) {
// Wrap the originally formatted message in color codes.
// If color is not supported in the terminal, log as is instead.
std::lock_guard<mutex_t> lock(mutex_);
@@ -47,99 +46,90 @@ SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::log(const details::log_msg &msg
msg.color_range_end = 0;
memory_buf_t formatted;
formatter_->format(msg, formatted);
if (should_do_colors_ && msg.color_range_end > msg.color_range_start)
{
if (should_do_colors_ && msg.color_range_end > msg.color_range_start) {
// before color range
print_range_(formatted, 0, msg.color_range_start);
// in color range
print_ccode_(colors_[static_cast<size_t>(msg.level)]);
print_ccode_(colors_.at(static_cast<size_t>(msg.level)));
print_range_(formatted, msg.color_range_start, msg.color_range_end);
print_ccode_(reset);
// after color range
print_range_(formatted, msg.color_range_end, formatted.size());
}
else // no color
} else // no color
{
print_range_(formatted, 0, formatted.size());
}
fflush(target_file_);
}
template<typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::flush()
{
template <typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::flush() {
std::lock_guard<mutex_t> lock(mutex_);
fflush(target_file_);
}
template<typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_pattern(const std::string &pattern)
{
template <typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_pattern(const std::string &pattern) {
std::lock_guard<mutex_t> lock(mutex_);
formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern));
}
template<typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter)
{
template <typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_formatter(
std::unique_ptr<spdlog::formatter> sink_formatter) {
std::lock_guard<mutex_t> lock(mutex_);
formatter_ = std::move(sink_formatter);
}
template<typename ConsoleMutex>
SPDLOG_INLINE bool ansicolor_sink<ConsoleMutex>::should_color()
{
template <typename ConsoleMutex>
SPDLOG_INLINE bool ansicolor_sink<ConsoleMutex>::should_color() {
return should_do_colors_;
}
template<typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color_mode(color_mode mode)
{
switch (mode)
{
case color_mode::always:
should_do_colors_ = true;
return;
case color_mode::automatic:
should_do_colors_ = details::os::in_terminal(target_file_) && details::os::is_color_terminal();
return;
case color_mode::never:
should_do_colors_ = false;
return;
default:
should_do_colors_ = false;
template <typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color_mode(color_mode mode) {
switch (mode) {
case color_mode::always:
should_do_colors_ = true;
return;
case color_mode::automatic:
should_do_colors_ =
details::os::in_terminal(target_file_) && details::os::is_color_terminal();
return;
case color_mode::never:
should_do_colors_ = false;
return;
default:
should_do_colors_ = false;
}
}
template<typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_ccode_(const string_view_t &color_code)
{
template <typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_ccode_(const string_view_t &color_code) {
fwrite(color_code.data(), sizeof(char), color_code.size(), target_file_);
}
template<typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted, size_t start, size_t end)
{
template <typename ConsoleMutex>
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted,
size_t start,
size_t end) {
fwrite(formatted.data() + start, sizeof(char), end - start, target_file_);
}
template<typename ConsoleMutex>
SPDLOG_INLINE std::string ansicolor_sink<ConsoleMutex>::to_string_(const string_view_t &sv)
{
template <typename ConsoleMutex>
SPDLOG_INLINE std::string ansicolor_sink<ConsoleMutex>::to_string_(const string_view_t &sv) {
return std::string(sv.data(), sv.size());
}
// ansicolor_stdout_sink
template<typename ConsoleMutex>
template <typename ConsoleMutex>
SPDLOG_INLINE ansicolor_stdout_sink<ConsoleMutex>::ansicolor_stdout_sink(color_mode mode)
: ansicolor_sink<ConsoleMutex>(stdout, mode)
{}
: ansicolor_sink<ConsoleMutex>(stdout, mode) {}
// ansicolor_stderr_sink
template<typename ConsoleMutex>
template <typename ConsoleMutex>
SPDLOG_INLINE ansicolor_stderr_sink<ConsoleMutex>::ansicolor_stderr_sink(color_mode mode)
: ansicolor_sink<ConsoleMutex>(stderr, mode)
{}
: ansicolor_sink<ConsoleMutex>(stderr, mode) {}
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog

View File

@@ -3,13 +3,13 @@
#pragma once
#include <array>
#include <memory>
#include <mutex>
#include <spdlog/details/console_globals.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/sink.h>
#include <memory>
#include <mutex>
#include <string>
#include <array>
namespace spdlog {
namespace sinks {
@@ -21,9 +21,8 @@ namespace sinks {
* If no color terminal detected, omit the escape codes.
*/
template<typename ConsoleMutex>
class ansicolor_sink : public sink
{
template <typename ConsoleMutex>
class ansicolor_sink : public sink {
public:
using mutex_t = typename ConsoleMutex::mutex_t;
ansicolor_sink(FILE *target_file, color_mode mode);
@@ -90,16 +89,14 @@ private:
static std::string to_string_(const string_view_t &sv);
};
template<typename ConsoleMutex>
class ansicolor_stdout_sink : public ansicolor_sink<ConsoleMutex>
{
template <typename ConsoleMutex>
class ansicolor_stdout_sink : public ansicolor_sink<ConsoleMutex> {
public:
explicit ansicolor_stdout_sink(color_mode mode = color_mode::automatic);
};
template<typename ConsoleMutex>
class ansicolor_stderr_sink : public ansicolor_sink<ConsoleMutex>
{
template <typename ConsoleMutex>
class ansicolor_stderr_sink : public ansicolor_sink<ConsoleMutex> {
public:
explicit ansicolor_stderr_sink(color_mode mode = color_mode::automatic);
};
@@ -110,9 +107,9 @@ using ansicolor_stdout_sink_st = ansicolor_stdout_sink<details::console_nullmute
using ansicolor_stderr_sink_mt = ansicolor_stderr_sink<details::console_mutex>;
using ansicolor_stderr_sink_st = ansicolor_stderr_sink<details::console_nullmutex>;
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
# include "ansicolor_sink-inl.h"
#include "ansicolor_sink-inl.h"
#endif

View File

@@ -4,60 +4,56 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
# include <spdlog/sinks/base_sink.h>
#include <spdlog/sinks/base_sink.h>
#endif
#include <spdlog/common.h>
#include <spdlog/pattern_formatter.h>
#include <memory>
#include <mutex>
template<typename Mutex>
template <typename Mutex>
SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::base_sink()
: formatter_{details::make_unique<spdlog::pattern_formatter>()}
{}
: formatter_{details::make_unique<spdlog::pattern_formatter>()} {}
template<typename Mutex>
SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::base_sink(std::unique_ptr<spdlog::formatter> formatter)
: formatter_{std::move(formatter)}
{}
template <typename Mutex>
SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::base_sink(
std::unique_ptr<spdlog::formatter> formatter)
: formatter_{std::move(formatter)} {}
template<typename Mutex>
void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::log(const details::log_msg &msg)
{
template <typename Mutex>
void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::log(const details::log_msg &msg) {
std::lock_guard<Mutex> lock(mutex_);
sink_it_(msg);
}
template<typename Mutex>
void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::flush()
{
template <typename Mutex>
void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::flush() {
std::lock_guard<Mutex> lock(mutex_);
flush_();
}
template<typename Mutex>
void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_pattern(const std::string &pattern)
{
template <typename Mutex>
void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_pattern(const std::string &pattern) {
std::lock_guard<Mutex> lock(mutex_);
set_pattern_(pattern);
}
template<typename Mutex>
void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter)
{
template <typename Mutex>
void SPDLOG_INLINE
spdlog::sinks::base_sink<Mutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) {
std::lock_guard<Mutex> lock(mutex_);
set_formatter_(std::move(sink_formatter));
}
template<typename Mutex>
void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_pattern_(const std::string &pattern)
{
template <typename Mutex>
void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_pattern_(const std::string &pattern) {
set_formatter_(details::make_unique<spdlog::pattern_formatter>(pattern));
}
template<typename Mutex>
void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter)
{
template <typename Mutex>
void SPDLOG_INLINE
spdlog::sinks::base_sink<Mutex>::set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter) {
formatter_ = std::move(sink_formatter);
}

View File

@@ -15,9 +15,8 @@
namespace spdlog {
namespace sinks {
template<typename Mutex>
class SPDLOG_API base_sink : public sink
{
template <typename Mutex>
class SPDLOG_API base_sink : public sink {
public:
base_sink();
explicit base_sink(std::unique_ptr<spdlog::formatter> formatter);
@@ -44,9 +43,9 @@ protected:
virtual void set_pattern_(const std::string &pattern);
virtual void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter);
};
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
# include "base_sink-inl.h"
#include "base_sink-inl.h"
#endif

View File

@@ -4,7 +4,7 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
# include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/basic_file_sink.h>
#endif
#include <spdlog/common.h>
@@ -13,32 +13,30 @@
namespace spdlog {
namespace sinks {
template<typename Mutex>
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}
{
template <typename Mutex>
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);
}
template<typename Mutex>
SPDLOG_INLINE const filename_t &basic_file_sink<Mutex>::filename() const
{
template <typename Mutex>
SPDLOG_INLINE const filename_t &basic_file_sink<Mutex>::filename() const {
return file_helper_.filename();
}
template<typename Mutex>
SPDLOG_INLINE void basic_file_sink<Mutex>::sink_it_(const details::log_msg &msg)
{
template <typename Mutex>
SPDLOG_INLINE void basic_file_sink<Mutex>::sink_it_(const details::log_msg &msg) {
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
file_helper_.write(formatted);
}
template<typename Mutex>
SPDLOG_INLINE void basic_file_sink<Mutex>::flush_()
{
template <typename Mutex>
SPDLOG_INLINE void basic_file_sink<Mutex>::flush_() {
file_helper_.flush();
}
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog

View File

@@ -5,8 +5,8 @@
#include <spdlog/details/file_helper.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/sinks/base_sink.h>
#include <mutex>
#include <string>
@@ -16,11 +16,12 @@ namespace sinks {
/*
* Trivial file sink with single file as target
*/
template<typename Mutex>
class basic_file_sink final : public base_sink<Mutex>
{
template <typename Mutex>
class basic_file_sink final : public base_sink<Mutex> {
public:
explicit basic_file_sink(const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {});
explicit basic_file_sink(const filename_t &filename,
bool truncate = false,
const file_event_handlers &event_handlers = {});
const filename_t &filename() const;
protected:
@@ -34,27 +35,31 @@ private:
using basic_file_sink_mt = basic_file_sink<std::mutex>;
using basic_file_sink_st = basic_file_sink<details::null_mutex>;
} // namespace sinks
} // namespace sinks
//
// 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, const file_event_handlers &event_handlers = {})
{
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_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,
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, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::basic_file_sink_st>(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,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::basic_file_sink_st>(logger_name, filename, truncate,
event_handlers);
}
} // namespace spdlog
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
# include "basic_file_sink-inl.h"
#include "basic_file_sink-inl.h"
#endif

56
vendor/spdlog/sinks/callback_sink.h vendored Normal file
View File

@@ -0,0 +1,56 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/sinks/base_sink.h>
#include <mutex>
#include <string>
namespace spdlog {
// callbacks type
typedef std::function<void(const details::log_msg &msg)> custom_log_callback;
namespace sinks {
/*
* Trivial callback sink, gets a callback function and calls it on each log
*/
template <typename Mutex>
class callback_sink final : public base_sink<Mutex> {
public:
explicit callback_sink(const custom_log_callback &callback)
: callback_{callback} {}
protected:
void sink_it_(const details::log_msg &msg) override { callback_(msg); }
void flush_() override{};
private:
custom_log_callback callback_;
};
using callback_sink_mt = callback_sink<std::mutex>;
using callback_sink_st = callback_sink<details::null_mutex>;
} // namespace sinks
//
// factory functions
//
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> callback_logger_mt(const std::string &logger_name,
const custom_log_callback &callback) {
return Factory::template create<sinks::callback_sink_mt>(logger_name, callback);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> callback_logger_st(const std::string &logger_name,
const custom_log_callback &callback) {
return Factory::template create<sinks::callback_sink_st>(logger_name, callback);
}
} // namespace spdlog

View File

@@ -4,19 +4,20 @@
#pragma once
#include <spdlog/common.h>
#include <spdlog/details/circular_q.h>
#include <spdlog/details/file_helper.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/fmt/fmt.h>
#include <spdlog/fmt/chrono.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/os.h>
#include <spdlog/details/circular_q.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/fmt/chrono.h>
#include <spdlog/fmt/fmt.h>
#include <spdlog/sinks/base_sink.h>
#include <chrono>
#include <cstdio>
#include <ctime>
#include <iomanip>
#include <mutex>
#include <sstream>
#include <string>
namespace spdlog {
@@ -25,85 +26,36 @@ namespace sinks {
/*
* Generator of daily log file names in format basename.YYYY-MM-DD.ext
*/
struct daily_filename_calculator
{
struct daily_filename_calculator {
// Create filename for the form basename.YYYY-MM-DD
static filename_t calc_filename(const filename_t &filename, const tm &now_tm)
{
static filename_t calc_filename(const filename_t &filename, const tm &now_tm) {
filename_t basename, ext;
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
return fmt_lib::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);
}
};
/*
* Generator of daily log file names with strftime format.
* Usages:
* auto sink = std::make_shared<spdlog::sinks::daily_file_format_sink_mt>("myapp-%Y-%m-%d:%H:%M:%S.log", hour, minute);"
* auto logger = spdlog::daily_logger_format_mt("loggername, "myapp-%Y-%m-%d:%X.log", hour, minute)"
* auto sink =
* std::make_shared<spdlog::sinks::daily_file_format_sink_mt>("myapp-%Y-%m-%d:%H:%M:%S.log", hour,
* minute);" auto logger = spdlog::daily_logger_format_mt("loggername, "myapp-%Y-%m-%d:%X.log",
* hour, minute)"
*
*/
struct daily_filename_format_calculator
{
static filename_t calc_filename(const filename_t &filename, const tm &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;
struct daily_filename_format_calculator {
static filename_t calc_filename(const filename_t &file_path, const tm &now_tm) {
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
std::wstringstream stream;
#else
// 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 doesn't allow fmt::runtime(..) with wchar here
return fmt::format(fmt_filename, now_tm);
# else
return fmt::format(SPDLOG_FMT_RUNTIME(fmt_filename), now_tm);
# endif
std::stringstream stream;
#endif
stream << std::put_time(&now_tm, file_path.c_str());
return stream.str();
}
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
};
/*
@@ -111,23 +63,25 @@ private:
* If truncate != false , the created file will be truncated.
* If max_files > 0, retain only the last max_files and delete previous.
*/
template<typename Mutex, typename FileNameCalc = daily_filename_calculator>
class daily_file_sink final : public base_sink<Mutex>
{
template <typename Mutex, typename FileNameCalc = daily_filename_calculator>
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,
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_()
{
if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
{
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_() {
if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 ||
rotation_minute > 59) {
throw_spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
}
@@ -136,25 +90,21 @@ public:
file_helper_.open(filename, truncate_);
rotation_tp_ = next_rotation_tp_();
if (max_files_ > 0)
{
if (max_files_ > 0) {
init_filenames_q_();
}
}
filename_t filename()
{
filename_t filename() {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
return file_helper_.filename();
}
protected:
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
auto time = msg.time;
bool should_rotate = time >= rotation_tp_;
if (should_rotate)
{
if (should_rotate) {
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time));
file_helper_.open(filename, truncate_);
rotation_tp_ = next_rotation_tp_();
@@ -164,57 +114,46 @@ protected:
file_helper_.write(formatted);
// Do the cleaning only at the end because it might throw on failure.
if (should_rotate && max_files_ > 0)
{
if (should_rotate && max_files_ > 0) {
delete_old_();
}
}
void flush_() override
{
file_helper_.flush();
}
void flush_() override { file_helper_.flush(); }
private:
void init_filenames_q_()
{
void init_filenames_q_() {
using details::os::path_exists;
filenames_q_ = details::circular_q<filename_t>(static_cast<size_t>(max_files_));
std::vector<filename_t> filenames;
auto now = log_clock::now();
while (filenames.size() < max_files_)
{
while (filenames.size() < max_files_) {
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));
if (!path_exists(filename))
{
if (!path_exists(filename)) {
break;
}
filenames.emplace_back(filename);
now -= std::chrono::hours(24);
}
for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter)
{
for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter) {
filenames_q_.push_back(std::move(*iter));
}
}
tm now_tm(log_clock::time_point tp)
{
tm now_tm(log_clock::time_point tp) {
time_t tnow = log_clock::to_time_t(tp);
return spdlog::details::os::localtime(tnow);
}
log_clock::time_point next_rotation_tp_()
{
log_clock::time_point next_rotation_tp_() {
auto now = log_clock::now();
tm date = now_tm(now);
date.tm_hour = rotation_h_;
date.tm_min = rotation_m_;
date.tm_sec = 0;
auto rotation_time = log_clock::from_time_t(std::mktime(&date));
if (rotation_time > now)
{
if (rotation_time > now) {
return rotation_time;
}
return {rotation_time + std::chrono::hours(24)};
@@ -222,21 +161,19 @@ private:
// Delete the file N rotations ago.
// Throw spdlog_ex on failure to delete the old file.
void delete_old_()
{
void delete_old_() {
using details::os::filename_to_str;
using details::os::remove_if_exists;
filename_t current_file = file_helper_.filename();
if (filenames_q_.full())
{
if (filenames_q_.full()) {
auto old_filename = std::move(filenames_q_.front());
filenames_q_.pop_front();
bool ok = remove_if_exists(old_filename) == 0;
if (!ok)
{
if (!ok) {
filenames_q_.push_back(std::move(current_file));
throw_spdlog_ex("Failed removing daily file " + filename_to_str(old_filename), errno);
throw_spdlog_ex("Failed removing daily file " + filename_to_str(old_filename),
errno);
}
}
filenames_q_.push_back(std::move(current_file));
@@ -255,40 +192,61 @@ private:
using daily_file_sink_mt = daily_file_sink<std::mutex>;
using daily_file_sink_st = daily_file_sink<details::null_mutex>;
using daily_file_format_sink_mt = daily_file_sink<std::mutex, daily_filename_format_calculator>;
using daily_file_format_sink_st = daily_file_sink<details::null_mutex, daily_filename_format_calculator>;
using daily_file_format_sink_st =
daily_file_sink<details::null_mutex, daily_filename_format_calculator>;
} // namespace sinks
} // namespace sinks
//
// 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, const file_event_handlers &event_handlers = {})
{
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_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, 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, const file_event_handlers &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,
const file_event_handlers &event_handlers = {}) {
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, const file_event_handlers &event_handlers = {})
{
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_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, 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, const file_event_handlers &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,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::daily_file_format_sink_st>(
logger_name, filename, hour, minute, truncate, max_files, event_handlers);
}
} // namespace spdlog
} // namespace spdlog

View File

@@ -19,72 +19,56 @@
namespace spdlog {
namespace sinks {
template<typename Mutex>
class dist_sink : public base_sink<Mutex>
{
template <typename Mutex>
class dist_sink : public base_sink<Mutex> {
public:
dist_sink() = default;
explicit dist_sink(std::vector<std::shared_ptr<sink>> sinks)
: sinks_(sinks)
{}
: sinks_(sinks) {}
dist_sink(const dist_sink &) = delete;
dist_sink &operator=(const dist_sink &) = delete;
void add_sink(std::shared_ptr<sink> sink)
{
void add_sink(std::shared_ptr<sink> sub_sink) {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
sinks_.push_back(sink);
sinks_.push_back(sub_sink);
}
void remove_sink(std::shared_ptr<sink> sink)
{
void remove_sink(std::shared_ptr<sink> sub_sink) {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink), sinks_.end());
sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sub_sink), sinks_.end());
}
void set_sinks(std::vector<std::shared_ptr<sink>> sinks)
{
void set_sinks(std::vector<std::shared_ptr<sink>> sinks) {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
sinks_ = std::move(sinks);
}
std::vector<std::shared_ptr<sink>> &sinks()
{
return sinks_;
}
std::vector<std::shared_ptr<sink>> &sinks() { return sinks_; }
protected:
void sink_it_(const details::log_msg &msg) override
{
for (auto &sink : sinks_)
{
if (sink->should_log(msg.level))
{
sink->log(msg);
void sink_it_(const details::log_msg &msg) override {
for (auto &sub_sink : sinks_) {
if (sub_sink->should_log(msg.level)) {
sub_sink->log(msg);
}
}
}
void flush_() override
{
for (auto &sink : sinks_)
{
sink->flush();
void flush_() override {
for (auto &sub_sink : sinks_) {
sub_sink->flush();
}
}
void set_pattern_(const std::string &pattern) override
{
void set_pattern_(const std::string &pattern) override {
set_formatter_(details::make_unique<spdlog::pattern_formatter>(pattern));
}
void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter) override
{
void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter) override {
base_sink<Mutex>::formatter_ = std::move(sink_formatter);
for (auto &sink : sinks_)
{
sink->set_formatter(base_sink<Mutex>::formatter_->clone());
for (auto &sub_sink : sinks_) {
sub_sink->set_formatter(base_sink<Mutex>::formatter_->clone());
}
}
std::vector<std::shared_ptr<sink>> sinks_;
@@ -93,5 +77,5 @@ protected:
using dist_sink_mt = dist_sink<std::mutex>;
using dist_sink_st = dist_sink<details::null_mutex>;
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog

View File

@@ -4,13 +4,13 @@
#pragma once
#include "dist_sink.h"
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/log_msg.h>
#include <spdlog/details/null_mutex.h>
#include <chrono>
#include <cstdio>
#include <mutex>
#include <string>
#include <chrono>
// Duplicate message removal sink.
// Skip the message if previous one is identical and less than "max_skip_duration" have passed
@@ -20,8 +20,8 @@
// #include <spdlog/sinks/dup_filter_sink.h>
//
// int main() {
// auto dup_filter = std::make_shared<dup_filter_sink_st>(std::chrono::seconds(5));
// dup_filter->add_sink(std::make_shared<stdout_color_sink_mt>());
// auto dup_filter = std::make_shared<dup_filter_sink_st>(std::chrono::seconds(5),
// level::info); dup_filter->add_sink(std::make_shared<stdout_color_sink_mt>());
// spdlog::logger l("logger", dup_filter);
// l.info("Hello");
// l.info("Hello");
@@ -36,38 +36,37 @@
namespace spdlog {
namespace sinks {
template<typename Mutex>
class dup_filter_sink : public dist_sink<Mutex>
{
template <typename Mutex>
class dup_filter_sink : public dist_sink<Mutex> {
public:
template<class Rep, class Period>
explicit dup_filter_sink(std::chrono::duration<Rep, Period> max_skip_duration)
: max_skip_duration_{max_skip_duration}
{}
template <class Rep, class Period>
explicit dup_filter_sink(std::chrono::duration<Rep, Period> max_skip_duration,
level::level_enum notification_level = level::info)
: max_skip_duration_{max_skip_duration},
log_level_{notification_level} {}
protected:
std::chrono::microseconds max_skip_duration_;
log_clock::time_point last_msg_time_;
std::string last_msg_payload_;
size_t skip_counter_ = 0;
level::level_enum log_level_;
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
bool filtered = filter_(msg);
if (!filtered)
{
if (!filtered) {
skip_counter_ += 1;
return;
}
// log the "skipped.." message
if (skip_counter_ > 0)
{
if (skip_counter_ > 0) {
char buf[64];
auto msg_size = ::snprintf(buf, sizeof(buf), "Skipped %u duplicate messages..", static_cast<unsigned>(skip_counter_));
if (msg_size > 0 && static_cast<size_t>(msg_size) < sizeof(buf))
{
details::log_msg skipped_msg{msg.logger_name, level::info, string_view_t{buf, static_cast<size_t>(msg_size)}};
auto msg_size = ::snprintf(buf, sizeof(buf), "Skipped %u duplicate messages..",
static_cast<unsigned>(skip_counter_));
if (msg_size > 0 && static_cast<size_t>(msg_size) < sizeof(buf)) {
details::log_msg skipped_msg{msg.source, msg.logger_name, log_level_,
string_view_t{buf, static_cast<size_t>(msg_size)}};
dist_sink<Mutex>::sink_it_(skipped_msg);
}
}
@@ -80,8 +79,7 @@ protected:
}
// return whether the log msg should be displayed (true) or skipped (false)
bool filter_(const details::log_msg &msg)
{
bool filter_(const details::log_msg &msg) {
auto filter_duration = msg.time - last_msg_time_;
return (filter_duration > max_skip_duration_) || (msg.payload != last_msg_payload_);
}
@@ -90,5 +88,5 @@ protected:
using dup_filter_sink_mt = dup_filter_sink<std::mutex>;
using dup_filter_sink_st = dup_filter_sink<details::null_mutex>;
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog

View File

@@ -4,13 +4,13 @@
#pragma once
#include <spdlog/common.h>
#include <spdlog/details/circular_q.h>
#include <spdlog/details/file_helper.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/os.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/fmt/fmt.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/os.h>
#include <spdlog/details/circular_q.h>
#include <spdlog/details/synchronous_factory.h>
#include <chrono>
#include <cstdio>
@@ -24,15 +24,14 @@ namespace sinks {
/*
* Generator of Hourly log file names in format basename.YYYY-MM-DD-HH.ext
*/
struct hourly_filename_calculator
{
struct hourly_filename_calculator {
// Create filename for the form basename.YYYY-MM-DD-H
static filename_t calc_filename(const filename_t &filename, const tm &now_tm)
{
static filename_t calc_filename(const filename_t &filename, const tm &now_tm) {
filename_t basename, ext;
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
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);
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);
}
};
@@ -41,102 +40,93 @@ struct hourly_filename_calculator
* If truncate != false , the created file will be truncated.
* If max_files > 0, retain only the last max_files and delete previous.
*/
template<typename Mutex, typename FileNameCalc = hourly_filename_calculator>
class hourly_file_sink final : public base_sink<Mutex>
{
template <typename Mutex, typename FileNameCalc = hourly_filename_calculator>
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, const file_event_handlers &event_handlers = {})
: base_filename_(std::move(base_filename))
, file_helper_{event_handlers}
, truncate_(truncate)
, max_files_(max_files)
, filenames_q_()
{
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_() {
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)
{
if (max_files_ > 0) {
init_filenames_q_();
}
}
filename_t filename()
{
filename_t filename() {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
return file_helper_.filename();
}
protected:
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
auto time = msg.time;
bool should_rotate = time >= rotation_tp_;
if (should_rotate)
{
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);
// Do the cleaning only at the end because it might throw on failure.
if (should_rotate && max_files_ > 0)
{
if (should_rotate && max_files_ > 0) {
delete_old_();
}
}
void flush_() override
{
file_helper_.flush();
}
void flush_() override { file_helper_.flush(); }
private:
void init_filenames_q_()
{
void init_filenames_q_() {
using details::os::path_exists;
filenames_q_ = details::circular_q<filename_t>(static_cast<size_t>(max_files_));
std::vector<filename_t> filenames;
auto now = log_clock::now();
while (filenames.size() < max_files_)
{
while (filenames.size() < max_files_) {
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));
if (!path_exists(filename))
{
if (!path_exists(filename)) {
break;
}
filenames.emplace_back(filename);
now -= std::chrono::hours(1);
}
for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter)
{
for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter) {
filenames_q_.push_back(std::move(*iter));
}
}
tm now_tm(log_clock::time_point tp)
{
tm now_tm(log_clock::time_point tp) {
time_t tnow = log_clock::to_time_t(tp);
return spdlog::details::os::localtime(tnow);
}
log_clock::time_point next_rotation_tp_()
{
log_clock::time_point next_rotation_tp_() {
auto now = log_clock::now();
tm date = now_tm(now);
date.tm_min = 0;
date.tm_sec = 0;
auto rotation_time = log_clock::from_time_t(std::mktime(&date));
if (rotation_time > now)
{
if (rotation_time > now) {
return rotation_time;
}
return {rotation_time + std::chrono::hours(1)};
@@ -144,21 +134,19 @@ private:
// Delete the file N rotations ago.
// Throw spdlog_ex on failure to delete the old file.
void delete_old_()
{
void delete_old_() {
using details::os::filename_to_str;
using details::os::remove_if_exists;
filename_t current_file = file_helper_.filename();
if (filenames_q_.full())
{
if (filenames_q_.full()) {
auto old_filename = std::move(filenames_q_.front());
filenames_q_.pop_front();
bool ok = remove_if_exists(old_filename) == 0;
if (!ok)
{
if (!ok) {
filenames_q_.push_back(std::move(current_file));
SPDLOG_THROW(spdlog_ex("Failed removing hourly file " + filename_to_str(old_filename), errno));
SPDLOG_THROW(spdlog_ex(
"Failed removing hourly file " + filename_to_str(old_filename), errno));
}
}
filenames_q_.push_back(std::move(current_file));
@@ -170,27 +158,34 @@ 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>;
using hourly_file_sink_st = hourly_file_sink<details::null_mutex>;
} // namespace sinks
} // namespace sinks
//
// 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, const file_event_handlers &event_handlers = {})
{
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_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, 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, const file_event_handlers &event_handlers = {})
{
return Factory::template create<sinks::hourly_file_sink_st>(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,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::hourly_file_sink_st>(logger_name, filename, truncate,
max_files, event_handlers);
}
} // namespace spdlog
} // namespace spdlog

119
vendor/spdlog/sinks/kafka_sink.h vendored Normal file
View File

@@ -0,0 +1,119 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
//
// Custom sink for kafka
// Building and using requires librdkafka library.
// For building librdkafka library check the url below
// https://github.com/confluentinc/librdkafka
//
#include "spdlog/async.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/details/synchronous_factory.h"
#include "spdlog/sinks/base_sink.h"
#include <mutex>
#include <spdlog/common.h>
// kafka header
#include <librdkafka/rdkafkacpp.h>
namespace spdlog {
namespace sinks {
struct kafka_sink_config {
std::string server_addr;
std::string produce_topic;
int32_t flush_timeout_ms = 1000;
kafka_sink_config(std::string addr, std::string topic, int flush_timeout_ms = 1000)
: server_addr{std::move(addr)},
produce_topic{std::move(topic)},
flush_timeout_ms(flush_timeout_ms) {}
};
template <typename Mutex>
class kafka_sink : public base_sink<Mutex> {
public:
kafka_sink(kafka_sink_config config)
: config_{std::move(config)} {
try {
std::string errstr;
conf_.reset(RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL));
RdKafka::Conf::ConfResult confRes =
conf_->set("bootstrap.servers", config_.server_addr, errstr);
if (confRes != RdKafka::Conf::CONF_OK) {
throw_spdlog_ex(
fmt_lib::format("conf set bootstrap.servers failed err:{}", errstr));
}
tconf_.reset(RdKafka::Conf::create(RdKafka::Conf::CONF_TOPIC));
if (tconf_ == nullptr) {
throw_spdlog_ex(fmt_lib::format("create topic config failed"));
}
producer_.reset(RdKafka::Producer::create(conf_.get(), errstr));
if (producer_ == nullptr) {
throw_spdlog_ex(fmt_lib::format("create producer failed err:{}", errstr));
}
topic_.reset(RdKafka::Topic::create(producer_.get(), config_.produce_topic,
tconf_.get(), errstr));
if (topic_ == nullptr) {
throw_spdlog_ex(fmt_lib::format("create topic failed err:{}", errstr));
}
} catch (const std::exception &e) {
throw_spdlog_ex(fmt_lib::format("error create kafka instance: {}", e.what()));
}
}
~kafka_sink() { producer_->flush(config_.flush_timeout_ms); }
protected:
void sink_it_(const details::log_msg &msg) override {
producer_->produce(topic_.get(), 0, RdKafka::Producer::RK_MSG_COPY,
(void *)msg.payload.data(), msg.payload.size(), NULL, NULL);
}
void flush_() override { producer_->flush(config_.flush_timeout_ms); }
private:
kafka_sink_config config_;
std::unique_ptr<RdKafka::Producer> producer_ = nullptr;
std::unique_ptr<RdKafka::Conf> conf_ = nullptr;
std::unique_ptr<RdKafka::Conf> tconf_ = nullptr;
std::unique_ptr<RdKafka::Topic> topic_ = nullptr;
};
using kafka_sink_mt = kafka_sink<std::mutex>;
using kafka_sink_st = kafka_sink<spdlog::details::null_mutex>;
} // namespace sinks
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> kafka_logger_mt(const std::string &logger_name,
spdlog::sinks::kafka_sink_config config) {
return Factory::template create<sinks::kafka_sink_mt>(logger_name, config);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> kafka_logger_st(const std::string &logger_name,
spdlog::sinks::kafka_sink_config config) {
return Factory::template create<sinks::kafka_sink_st>(logger_name, config);
}
template <typename Factory = spdlog::async_factory>
inline std::shared_ptr<spdlog::logger> kafka_logger_async_mt(
std::string logger_name, spdlog::sinks::kafka_sink_config config) {
return Factory::template create<sinks::kafka_sink_mt>(logger_name, config);
}
template <typename Factory = spdlog::async_factory>
inline std::shared_ptr<spdlog::logger> kafka_logger_async_st(
std::string logger_name, spdlog::sinks::kafka_sink_config config) {
return Factory::template create<sinks::kafka_sink_st>(logger_name, config);
}
} // namespace spdlog

View File

@@ -25,41 +25,46 @@
namespace spdlog {
namespace sinks {
template<typename Mutex>
class mongo_sink : public base_sink<Mutex>
{
template <typename Mutex>
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(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)
{
throw spdlog_ex("Error opening database");
} catch (const std::exception &e) {
throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what()));
}
}
~mongo_sink()
{
flush_();
}
~mongo_sink() { flush_(); }
protected:
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
using bsoncxx::builder::stream::document;
using bsoncxx::builder::stream::finalize;
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"
<< static_cast<int>(msg.thread_id) << finalize;
if (client_ != nullptr) {
auto doc = document{} << "timestamp" << bsoncxx::types::b_date(msg.time) << "level"
<< level::to_string_view(msg.level).data() << "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,33 +72,37 @@ 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;
};
template<>
mongocxx::instance mongo_sink<std::mutex>::instance_{};
#include "spdlog/details/null_mutex.h"
#include <mutex>
using mongo_sink_mt = mongo_sink<std::mutex>;
using mongo_sink_st = mongo_sink<spdlog::details::null_mutex>;
} // namespace sinks
} // namespace sinks
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> mongo_logger_mt(const std::string &logger_name, const std::string &db_name,
const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017")
{
return Factory::template create<sinks::mongo_sink_mt>(logger_name, db_name, collection_name, uri);
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> mongo_logger_mt(
const std::string &logger_name,
const std::string &db_name,
const std::string &collection_name,
const std::string &uri = "mongodb://localhost:27017") {
return Factory::template create<sinks::mongo_sink_mt>(logger_name, db_name, collection_name,
uri);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> mongo_logger_st(const std::string &logger_name, const std::string &db_name,
const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017")
{
return Factory::template create<sinks::mongo_sink_st>(logger_name, db_name, collection_name, uri);
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> mongo_logger_st(
const std::string &logger_name,
const std::string &db_name,
const std::string &collection_name,
const std::string &uri = "mongodb://localhost:27017") {
return Factory::template create<sinks::mongo_sink_st>(logger_name, db_name, collection_name,
uri);
}
} // namespace spdlog
} // namespace spdlog

View File

@@ -1,40 +1,59 @@
// 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>
# include <spdlog/sinks/base_sink.h>
#include <spdlog/details/null_mutex.h>
#if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
#include <spdlog/details/os.h>
#endif
#include <spdlog/sinks/base_sink.h>
# include <mutex>
# include <string>
#include <mutex>
#include <string>
// Avoid including windows.h (https://stackoverflow.com/a/30741042)
// Avoid including windows.h (https://stackoverflow.com/a/30741042)
#if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringW(const wchar_t *lpOutputString);
#else
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char *lpOutputString);
#endif
extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
namespace spdlog {
namespace sinks {
/*
* MSVC sink (logging using OutputDebugStringA)
*/
template<typename Mutex>
class msvc_sink : public base_sink<Mutex>
{
template <typename Mutex>
class msvc_sink : public base_sink<Mutex> {
public:
msvc_sink() = default;
msvc_sink(bool check_debugger_present)
: check_debugger_present_{check_debugger_present} {};
protected:
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
if (check_debugger_present_ && !IsDebuggerPresent()) {
return;
}
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
formatted.push_back('\0'); // add a null terminator for OutputDebugStringA
formatted.push_back('\0'); // add a null terminator for OutputDebugString
#if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
wmemory_buf_t wformatted;
details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), wformatted);
OutputDebugStringW(wformatted.data());
#else
OutputDebugStringA(formatted.data());
#endif
}
void flush_() override {}
bool check_debugger_present_ = true;
};
using msvc_sink_mt = msvc_sink<std::mutex>;
@@ -43,7 +62,7 @@ using msvc_sink_st = msvc_sink<details::null_mutex>;
using windebug_sink_mt = msvc_sink_mt;
using windebug_sink_st = msvc_sink_st;
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog
#endif

View File

@@ -4,17 +4,16 @@
#pragma once
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/sinks/base_sink.h>
#include <mutex>
namespace spdlog {
namespace sinks {
template<typename Mutex>
class null_sink : public base_sink<Mutex>
{
template <typename Mutex>
class null_sink : public base_sink<Mutex> {
protected:
void sink_it_(const details::log_msg &) override {}
void flush_() override {}
@@ -23,22 +22,20 @@ protected:
using null_sink_mt = null_sink<details::null_mutex>;
using null_sink_st = null_sink<details::null_mutex>;
} // namespace sinks
} // namespace sinks
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> null_logger_mt(const std::string &logger_name)
{
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> null_logger_mt(const std::string &logger_name) {
auto null_logger = Factory::template create<sinks::null_sink_mt>(logger_name);
null_logger->set_level(level::off);
return null_logger;
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> null_logger_st(const std::string &logger_name)
{
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> null_logger_st(const std::string &logger_name) {
auto null_logger = Factory::template create<sinks::null_sink_st>(logger_name);
null_logger->set_level(level::off);
return null_logger;
}
} // namespace spdlog
} // namespace spdlog

View File

@@ -11,33 +11,26 @@
namespace spdlog {
namespace sinks {
template<typename Mutex>
class ostream_sink final : public base_sink<Mutex>
{
template <typename Mutex>
class ostream_sink final : public base_sink<Mutex> {
public:
explicit ostream_sink(std::ostream &os, bool force_flush = false)
: ostream_(os)
, force_flush_(force_flush)
{}
: ostream_(os),
force_flush_(force_flush) {}
ostream_sink(const ostream_sink &) = delete;
ostream_sink &operator=(const ostream_sink &) = delete;
protected:
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
ostream_.write(formatted.data(), static_cast<std::streamsize>(formatted.size()));
if (force_flush_)
{
if (force_flush_) {
ostream_.flush();
}
}
void flush_() override
{
ostream_.flush();
}
void flush_() override { ostream_.flush(); }
std::ostream &ostream_;
bool force_flush_;
@@ -46,5 +39,5 @@ protected:
using ostream_sink_mt = ostream_sink<std::mutex>;
using ostream_sink_st = ostream_sink<details::null_mutex>;
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog

View File

@@ -4,45 +4,48 @@
#pragma once
//
// Custom sink for QPlainTextEdit or QTextEdit and its childs(QTextBrowser...
// Custom sink for QPlainTextEdit or QTextEdit and its children (QTextBrowser...
// etc) Building and using requires Qt library.
//
// Warning: the qt_sink won't be notified if the target widget is destroyed.
// If the widget's lifetime can be shorter than the logger's one, you should provide some permanent
// QObject, and then use a standard signal/slot.
//
#include "spdlog/common.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/synchronous_factory.h"
#include "spdlog/sinks/base_sink.h"
#include <array>
#include <QTextEdit>
#include <QPlainTextEdit>
#include <QTextEdit>
//
// qt_sink class
//
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, const std::string &meta_method)
{
qt_object_ = qt_object;
meta_method_ = meta_method;
qt_sink(QObject *qt_object, std::string meta_method)
: qt_object_(qt_object),
meta_method_(std::move(meta_method)) {
if (!qt_object_) {
throw_spdlog_ex("qt_sink: qt_object is null");
}
}
~qt_sink()
{
flush_();
}
~qt_sink() { flush_(); }
protected:
void sink_it_(const details::log_msg &msg) override
{
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,
const 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()));
}
@@ -53,50 +56,249 @@ private:
std::string meta_method_;
};
// Qt color sink to QTextEdit.
// Color location is determined by the sink log pattern like in the rest of spdlog sinks.
// Colors can be modified if needed using sink->set_color(level, qtTextCharFormat).
// max_lines is the maximum number of lines that the sink will hold before removing the oldest
// lines. By default, only ascii (latin1) is supported by this sink. Set is_utf8 to true if utf8
// support is needed.
template <typename Mutex>
class qt_color_sink : public base_sink<Mutex> {
public:
qt_color_sink(QTextEdit *qt_text_edit,
int max_lines,
bool dark_colors = false,
bool is_utf8 = false)
: qt_text_edit_(qt_text_edit),
max_lines_(max_lines),
is_utf8_(is_utf8) {
if (!qt_text_edit_) {
throw_spdlog_ex("qt_color_text_sink: text_edit is null");
}
default_color_ = qt_text_edit_->currentCharFormat();
// set colors
QTextCharFormat format;
// trace
format.setForeground(dark_colors ? Qt::darkGray : Qt::gray);
colors_.at(level::trace) = format;
// debug
format.setForeground(dark_colors ? Qt::darkCyan : Qt::cyan);
colors_.at(level::debug) = format;
// info
format.setForeground(dark_colors ? Qt::darkGreen : Qt::green);
colors_.at(level::info) = format;
// warn
format.setForeground(dark_colors ? Qt::darkYellow : Qt::yellow);
colors_.at(level::warn) = format;
// err
format.setForeground(Qt::red);
colors_.at(level::err) = format;
// critical
format.setForeground(Qt::white);
format.setBackground(Qt::red);
colors_.at(level::critical) = format;
}
~qt_color_sink() { flush_(); }
void set_default_color(QTextCharFormat format) {
// std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
default_color_ = format;
}
void set_level_color(level::level_enum color_level, QTextCharFormat format) {
// std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
colors_.at(static_cast<size_t>(color_level)) = format;
}
QTextCharFormat &get_level_color(level::level_enum color_level) {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
return colors_.at(static_cast<size_t>(color_level));
}
QTextCharFormat &get_default_color() {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
return default_color_;
}
protected:
struct invoke_params {
invoke_params(int max_lines,
QTextEdit *q_text_edit,
QString payload,
QTextCharFormat default_color,
QTextCharFormat level_color,
int color_range_start,
int color_range_end)
: max_lines(max_lines),
q_text_edit(q_text_edit),
payload(std::move(payload)),
default_color(default_color),
level_color(level_color),
color_range_start(color_range_start),
color_range_end(color_range_end) {}
int max_lines;
QTextEdit *q_text_edit;
QString payload;
QTextCharFormat default_color;
QTextCharFormat level_color;
int color_range_start;
int color_range_end;
};
void sink_it_(const details::log_msg &msg) override {
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
const string_view_t str = string_view_t(formatted.data(), formatted.size());
// apply the color to the color range in the formatted message.
QString payload;
int color_range_start = static_cast<int>(msg.color_range_start);
int color_range_end = static_cast<int>(msg.color_range_end);
if (is_utf8_) {
payload = QString::fromUtf8(str.data(), static_cast<int>(str.size()));
// convert color ranges from byte index to character index.
if (msg.color_range_start < msg.color_range_end) {
color_range_start = QString::fromUtf8(str.data(), msg.color_range_start).size();
color_range_end = QString::fromUtf8(str.data(), msg.color_range_end).size();
}
} else {
payload = QString::fromLatin1(str.data(), static_cast<int>(str.size()));
}
invoke_params params{max_lines_, // max lines
qt_text_edit_, // text edit to append to
std::move(payload), // text to append
default_color_, // default color
colors_.at(msg.level), // color to apply
color_range_start, // color range start
color_range_end}; // color range end
QMetaObject::invokeMethod(
qt_text_edit_, [params]() { invoke_method_(params); }, Qt::AutoConnection);
}
void flush_() override {}
// Add colored text to the text edit widget. This method is invoked in the GUI thread.
// It is a static method to ensure that it is handled correctly even if the sink is destroyed
// prematurely before it is invoked.
static void invoke_method_(invoke_params params) {
auto *document = params.q_text_edit->document();
QTextCursor cursor(document);
// remove first blocks if number of blocks exceeds max_lines
while (document->blockCount() > params.max_lines) {
cursor.select(QTextCursor::BlockUnderCursor);
cursor.removeSelectedText();
cursor.deleteChar(); // delete the newline after the block
}
cursor.movePosition(QTextCursor::End);
cursor.setCharFormat(params.default_color);
// if color range not specified or not not valid, just append the text with default color
if (params.color_range_end <= params.color_range_start) {
cursor.insertText(params.payload);
return;
}
// insert the text before the color range
cursor.insertText(params.payload.left(params.color_range_start));
// insert the colorized text
cursor.setCharFormat(params.level_color);
cursor.insertText(params.payload.mid(params.color_range_start,
params.color_range_end - params.color_range_start));
// insert the text after the color range with default format
cursor.setCharFormat(params.default_color);
cursor.insertText(params.payload.mid(params.color_range_end));
}
QTextEdit *qt_text_edit_;
int max_lines_;
bool is_utf8_;
QTextCharFormat default_color_;
std::array<QTextCharFormat, level::n_levels> colors_;
};
#include "spdlog/details/null_mutex.h"
#include <mutex>
using qt_sink_mt = qt_sink<std::mutex>;
using qt_sink_st = qt_sink<spdlog::details::null_mutex>;
} // namespace sinks
using qt_sink_st = qt_sink<details::null_mutex>;
using qt_color_sink_mt = qt_color_sink<std::mutex>;
using qt_color_sink_st = qt_color_sink<details::null_mutex>;
} // namespace sinks
//
// 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")
{
// log to QTextEdit
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")
{
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")
{
// log to QPlainTextEdit
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, 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,
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)
{
// log to QObject
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)
{
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
// log to QTextEdit with colorized output
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_color_logger_mt(const std::string &logger_name,
QTextEdit *qt_text_edit,
int max_lines,
bool is_utf8 = false) {
return Factory::template create<sinks::qt_color_sink_mt>(logger_name, qt_text_edit, max_lines,
false, is_utf8);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_color_logger_st(const std::string &logger_name,
QTextEdit *qt_text_edit,
int max_lines,
bool is_utf8 = false) {
return Factory::template create<sinks::qt_color_sink_st>(logger_name, qt_text_edit, max_lines,
false, is_utf8);
}
} // namespace spdlog

View File

@@ -3,10 +3,10 @@
#pragma once
#include "spdlog/sinks/base_sink.h"
#include "spdlog/details/circular_q.h"
#include "spdlog/details/log_msg_buffer.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/sinks/base_sink.h"
#include <mutex>
#include <string>
@@ -17,47 +17,40 @@ namespace sinks {
/*
* Ring buffer sink
*/
template<typename Mutex>
class ringbuffer_sink final : public base_sink<Mutex>
{
template <typename Mutex>
class ringbuffer_sink final : public base_sink<Mutex> {
public:
explicit ringbuffer_sink(size_t n_items)
: q_{n_items}
{}
: q_{n_items} {}
std::vector<details::log_msg_buffer> last_raw(size_t lim = 0)
{
std::vector<details::log_msg_buffer> last_raw(size_t lim = 0) {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
auto items_available = q_.size();
auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available;
std::vector<details::log_msg_buffer> ret;
ret.reserve(n_items);
for (size_t i = (items_available - n_items); i < items_available; i++)
{
for (size_t i = (items_available - n_items); i < items_available; i++) {
ret.push_back(q_.at(i));
}
return ret;
}
std::vector<std::string> last_formatted(size_t lim = 0)
{
std::vector<std::string> last_formatted(size_t lim = 0) {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
auto items_available = q_.size();
auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available;
std::vector<std::string> ret;
ret.reserve(n_items);
for (size_t i = (items_available - n_items); i < items_available; i++)
{
for (size_t i = (items_available - n_items); i < items_available; i++) {
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(q_.at(i), formatted);
ret.push_back(std::move(SPDLOG_BUF_TO_STRING(formatted)));
ret.push_back(SPDLOG_BUF_TO_STRING(formatted));
}
return ret;
}
protected:
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
q_.push_back(details::log_msg_buffer{msg});
}
void flush_() override {}
@@ -69,6 +62,6 @@ private:
using ringbuffer_sink_mt = ringbuffer_sink<std::mutex>;
using ringbuffer_sink_st = ringbuffer_sink<details::null_mutex>;
} // namespace sinks
} // namespace sinks
} // namespace spdlog
} // namespace spdlog

View File

@@ -4,7 +4,7 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
# include <spdlog/sinks/rotating_file_sink.h>
#include <spdlog/sinks/rotating_file_sink.h>
#endif
#include <spdlog/common.h>
@@ -23,27 +23,27 @@
namespace spdlog {
namespace sinks {
template<typename Mutex>
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, 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)
{
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)
{
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)
{
current_size_ = file_helper_.size(); // expensive. called only once
if (rotate_on_open && current_size_ > 0) {
rotate_();
current_size_ = 0;
}
@@ -51,11 +51,10 @@ SPDLOG_INLINE rotating_file_sink<Mutex>::rotating_file_sink(
// calc filename according to index and file extension if exists.
// e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
template<typename Mutex>
SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::calc_filename(const filename_t &filename, std::size_t index)
{
if (index == 0u)
{
template <typename Mutex>
SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::calc_filename(const filename_t &filename,
std::size_t index) {
if (index == 0u) {
return filename;
}
@@ -64,16 +63,14 @@ SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::calc_filename(const filename
return fmt_lib::format(SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext);
}
template<typename Mutex>
SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::filename()
{
template <typename Mutex>
SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::filename() {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
return file_helper_.filename();
}
template<typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::sink_it_(const details::log_msg &msg)
{
template <typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::sink_it_(const details::log_msg &msg) {
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
auto new_size = current_size_ + formatted.size();
@@ -81,11 +78,9 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::sink_it_(const details::log_msg &m
// 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_)
{
if (new_size > max_size_) {
file_helper_.flush();
if (file_helper_.size() > 0)
{
if (file_helper_.size() > 0) {
rotate_();
new_size = formatted.size();
}
@@ -94,9 +89,8 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::sink_it_(const details::log_msg &m
current_size_ = new_size;
}
template<typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::flush_()
{
template <typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::flush_() {
file_helper_.flush();
}
@@ -105,33 +99,31 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::flush_()
// log.1.txt -> log.2.txt
// log.2.txt -> log.3.txt
// log.3.txt -> delete
template<typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::rotate_()
{
template <typename Mutex>
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)
{
for (auto i = max_files_; i > 0; --i) {
filename_t src = calc_filename(base_filename_, i - 1);
if (!path_exists(src))
{
if (!path_exists(src)) {
continue;
}
filename_t target = calc_filename(base_filename_, i);
if (!rename_file_(src, target))
{
if (!rename_file_(src, target)) {
// if failed try again after a small delay.
// this is a workaround to a windows issue, where very high rotation
// rates can cause the rename to fail with permission denied (because of antivirus?).
details::os::sleep_for_millis(100);
if (!rename_file_(src, target))
{
file_helper_.reopen(true); // truncate the log file anyway to prevent it to grow beyond its limit!
if (!rename_file_(src, target)) {
file_helper_.reopen(
true); // truncate the log file anyway to prevent it to grow beyond its limit!
current_size_ = 0;
throw_spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno);
throw_spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) +
" to " + filename_to_str(target),
errno);
}
}
}
@@ -140,13 +132,13 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::rotate_()
// delete the target if exists, and rename the src file to target
// return true on success, false otherwise.
template<typename Mutex>
SPDLOG_INLINE bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src_filename, const filename_t &target_filename)
{
template <typename Mutex>
SPDLOG_INLINE bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src_filename,
const filename_t &target_filename) {
// try to delete the target file in case it already exists.
(void)details::os::remove(target_filename);
return details::os::rename(src_filename, target_filename) == 0;
}
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog

View File

@@ -3,10 +3,10 @@
#pragma once
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/file_helper.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/sinks/base_sink.h>
#include <chrono>
#include <mutex>
@@ -18,12 +18,14 @@ namespace sinks {
//
// Rotating file sink based on size
//
template<typename Mutex>
class rotating_file_sink final : public base_sink<Mutex>
{
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,
const file_event_handlers &event_handlers = {});
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();
@@ -53,29 +55,35 @@ private:
using rotating_file_sink_mt = rotating_file_sink<std::mutex>;
using rotating_file_sink_st = rotating_file_sink<details::null_mutex>;
} // namespace sinks
} // namespace sinks
//
// factory functions
//
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, const file_event_handlers &event_handlers = {})
{
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,
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, 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, const file_event_handlers &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,
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, event_handlers);
}
} // namespace spdlog
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
# include "rotating_file_sink-inl.h"
#include "rotating_file_sink-inl.h"
#endif

View File

@@ -4,22 +4,19 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
# include <spdlog/sinks/sink.h>
#include <spdlog/sinks/sink.h>
#endif
#include <spdlog/common.h>
SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const
{
SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const {
return msg_level >= level_.load(std::memory_order_relaxed);
}
SPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level)
{
SPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level) {
level_.store(log_level, std::memory_order_relaxed);
}
SPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const
{
SPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const {
return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed));
}

View File

@@ -9,8 +9,7 @@
namespace spdlog {
namespace sinks {
class SPDLOG_API sink
{
class SPDLOG_API sink {
public:
virtual ~sink() = default;
virtual void log(const details::log_msg &msg) = 0;
@@ -27,9 +26,9 @@ protected:
level_t level_{level::trace};
};
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
# include "sink-inl.h"
#include "sink-inl.h"
#endif

View File

@@ -4,35 +4,35 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
# include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#endif
#include <spdlog/logger.h>
#include <spdlog/common.h>
#include <spdlog/logger.h>
namespace spdlog {
template<typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode)
{
template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name,
color_mode mode) {
return Factory::template create<sinks::stdout_color_sink_mt>(logger_name, mode);
}
template<typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_color_st(const std::string &logger_name, color_mode mode)
{
template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_color_st(const std::string &logger_name,
color_mode mode) {
return Factory::template create<sinks::stdout_color_sink_st>(logger_name, mode);
}
template<typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, color_mode mode)
{
template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name,
color_mode mode) {
return Factory::template create<sinks::stderr_color_sink_mt>(logger_name, mode);
}
template<typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stderr_color_st(const std::string &logger_name, color_mode mode)
{
template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stderr_color_st(const std::string &logger_name,
color_mode mode) {
return Factory::template create<sinks::stderr_color_sink_st>(logger_name, mode);
}
} // namespace spdlog
} // namespace spdlog

View File

@@ -4,9 +4,9 @@
#pragma once
#ifdef _WIN32
# include <spdlog/sinks/wincolor_sink.h>
#include <spdlog/sinks/wincolor_sink.h>
#else
# include <spdlog/sinks/ansicolor_sink.h>
#include <spdlog/sinks/ansicolor_sink.h>
#endif
#include <spdlog/details/synchronous_factory.h>
@@ -24,22 +24,26 @@ using stdout_color_sink_st = ansicolor_stdout_sink_st;
using stderr_color_sink_mt = ansicolor_stderr_sink_mt;
using stderr_color_sink_st = ansicolor_stderr_sink_st;
#endif
} // namespace sinks
} // namespace sinks
template<typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic);
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name,
color_mode mode = color_mode::automatic);
template<typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic);
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_color_st(const std::string &logger_name,
color_mode mode = color_mode::automatic);
template<typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic);
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name,
color_mode mode = color_mode::automatic);
template<typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic);
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_color_st(const std::string &logger_name,
color_mode mode = color_mode::automatic);
} // namespace spdlog
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
# include "stdout_color_sinks-inl.h"
#include "stdout_color_sinks-inl.h"
#endif

View File

@@ -4,36 +4,35 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
# include <spdlog/sinks/stdout_sinks.h>
#include <spdlog/sinks/stdout_sinks.h>
#endif
#include <memory>
#include <spdlog/details/console_globals.h>
#include <spdlog/pattern_formatter.h>
#include <memory>
#ifdef _WIN32
// under windows using fwrite to non-binary stream results in \r\r\n (see issue #1675)
// so instead we use ::FileWrite
# include <spdlog/details/windows_include.h>
// under windows using fwrite to non-binary stream results in \r\r\n (see issue #1675)
// so instead we use ::FileWrite
#include <spdlog/details/windows_include.h>
# ifndef _USING_V110_SDK71_ // fileapi.h doesn't exist in winxp
# include <fileapi.h> // WriteFile (..)
# endif
#ifndef _USING_V110_SDK71_ // fileapi.h doesn't exist in winxp
#include <fileapi.h> // WriteFile (..)
#endif
# include <io.h> // _get_osfhandle(..)
# include <stdio.h> // _fileno(..)
#endif // WIN32
#include <io.h> // _get_osfhandle(..)
#include <stdio.h> // _fileno(..)
#endif // WIN32
namespace spdlog {
namespace sinks {
template<typename ConsoleMutex>
template <typename ConsoleMutex>
SPDLOG_INLINE stdout_sink_base<ConsoleMutex>::stdout_sink_base(FILE *file)
: mutex_(ConsoleMutex::mutex())
, file_(file)
, formatter_(details::make_unique<spdlog::pattern_formatter>())
{
: mutex_(ConsoleMutex::mutex()),
file_(file),
formatter_(details::make_unique<spdlog::pattern_formatter>()) {
#ifdef _WIN32
// get windows handle from the FILE* object
@@ -42,98 +41,86 @@ SPDLOG_INLINE stdout_sink_base<ConsoleMutex>::stdout_sink_base(FILE *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).
// throw only if non stdout/stderr target is requested (probably regular file and not console).
if (handle_ == INVALID_HANDLE_VALUE && file != stdout && file != stderr)
{
if (handle_ == INVALID_HANDLE_VALUE && file != stdout && file != stderr) {
throw_spdlog_ex("spdlog::stdout_sink_base: _get_osfhandle() failed", errno);
}
#endif // WIN32
#endif // WIN32
}
template<typename ConsoleMutex>
SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::log(const details::log_msg &msg)
{
template <typename ConsoleMutex>
SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::log(const details::log_msg &msg) {
#ifdef _WIN32
if (handle_ == INVALID_HANDLE_VALUE)
{
if (handle_ == INVALID_HANDLE_VALUE) {
return;
}
std::lock_guard<mutex_t> lock(mutex_);
memory_buf_t formatted;
formatter_->format(msg, formatted);
::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;
if (!ok)
{
throw_spdlog_ex("stdout_sink_base: WriteFile() failed. GetLastError(): " + std::to_string(::GetLastError()));
if (!ok) {
throw_spdlog_ex("stdout_sink_base: WriteFile() failed. GetLastError(): " +
std::to_string(::GetLastError()));
}
#else
std::lock_guard<mutex_t> lock(mutex_);
memory_buf_t formatted;
formatter_->format(msg, formatted);
::fwrite(formatted.data(), sizeof(char), formatted.size(), file_);
::fflush(file_); // flush every line to terminal
#endif // WIN32
#endif // WIN32
::fflush(file_); // flush every line to terminal
}
template<typename ConsoleMutex>
SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::flush()
{
template <typename ConsoleMutex>
SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::flush() {
std::lock_guard<mutex_t> lock(mutex_);
fflush(file_);
}
template<typename ConsoleMutex>
SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::set_pattern(const std::string &pattern)
{
template <typename ConsoleMutex>
SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::set_pattern(const std::string &pattern) {
std::lock_guard<mutex_t> lock(mutex_);
formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern));
}
template<typename ConsoleMutex>
SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter)
{
template <typename ConsoleMutex>
SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::set_formatter(
std::unique_ptr<spdlog::formatter> sink_formatter) {
std::lock_guard<mutex_t> lock(mutex_);
formatter_ = std::move(sink_formatter);
}
// stdout sink
template<typename ConsoleMutex>
template <typename ConsoleMutex>
SPDLOG_INLINE stdout_sink<ConsoleMutex>::stdout_sink()
: stdout_sink_base<ConsoleMutex>(stdout)
{}
: stdout_sink_base<ConsoleMutex>(stdout) {}
// stderr sink
template<typename ConsoleMutex>
template <typename ConsoleMutex>
SPDLOG_INLINE stderr_sink<ConsoleMutex>::stderr_sink()
: stdout_sink_base<ConsoleMutex>(stderr)
{}
: stdout_sink_base<ConsoleMutex>(stderr) {}
} // namespace sinks
} // namespace sinks
// factory methods
template<typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name)
{
template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name) {
return Factory::template create<sinks::stdout_sink_mt>(logger_name);
}
template<typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name)
{
template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name) {
return Factory::template create<sinks::stdout_sink_st>(logger_name);
}
template<typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name)
{
template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name) {
return Factory::template create<sinks::stderr_sink_mt>(logger_name);
}
template<typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name)
{
template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name) {
return Factory::template create<sinks::stderr_sink_st>(logger_name);
}
} // namespace spdlog
} // namespace spdlog

View File

@@ -3,22 +3,21 @@
#pragma once
#include <cstdio>
#include <spdlog/details/console_globals.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/sinks/sink.h>
#include <cstdio>
#ifdef _WIN32
# include <spdlog/details/windows_include.h>
#include <spdlog/details/windows_include.h>
#endif
namespace spdlog {
namespace sinks {
template<typename ConsoleMutex>
class stdout_sink_base : public sink
{
template <typename ConsoleMutex>
class stdout_sink_base : public sink {
public:
using mutex_t = typename ConsoleMutex::mutex_t;
explicit stdout_sink_base(FILE *file);
@@ -42,19 +41,17 @@ protected:
std::unique_ptr<spdlog::formatter> formatter_;
#ifdef _WIN32
HANDLE handle_;
#endif // WIN32
#endif // WIN32
};
template<typename ConsoleMutex>
class stdout_sink : public stdout_sink_base<ConsoleMutex>
{
template <typename ConsoleMutex>
class stdout_sink : public stdout_sink_base<ConsoleMutex> {
public:
stdout_sink();
};
template<typename ConsoleMutex>
class stderr_sink : public stdout_sink_base<ConsoleMutex>
{
template <typename ConsoleMutex>
class stderr_sink : public stdout_sink_base<ConsoleMutex> {
public:
stderr_sink();
};
@@ -65,23 +62,23 @@ using stdout_sink_st = stdout_sink<details::console_nullmutex>;
using stderr_sink_mt = stderr_sink<details::console_mutex>;
using stderr_sink_st = stderr_sink<details::console_nullmutex>;
} // namespace sinks
} // namespace sinks
// factory methods
template<typename Factory = spdlog::synchronous_factory>
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name);
template<typename Factory = spdlog::synchronous_factory>
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name);
template<typename Factory = spdlog::synchronous_factory>
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name);
template<typename Factory = spdlog::synchronous_factory>
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name);
} // namespace spdlog
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
# include "stdout_sinks-inl.h"
#include "stdout_sinks-inl.h"
#endif

View File

@@ -3,9 +3,9 @@
#pragma once
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/sinks/base_sink.h>
#include <array>
#include <string>
@@ -16,53 +16,42 @@ namespace sinks {
/**
* Sink that write to syslog using the `syscall()` library call.
*/
template<typename Mutex>
class syslog_sink : public base_sink<Mutex>
{
template <typename Mutex>
class syslog_sink : public base_sink<Mutex> {
public:
syslog_sink(std::string ident, int syslog_option, int syslog_facility, bool enable_formatting)
: 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,
/* spdlog::level::err */ LOG_ERR,
/* spdlog::level::critical */ LOG_CRIT,
/* spdlog::level::off */ LOG_INFO}}
, 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,
/* spdlog::level::err */ LOG_ERR,
/* spdlog::level::critical */ LOG_CRIT,
/* spdlog::level::off */ LOG_INFO}},
ident_{std::move(ident)} {
// set ident to be program name if empty
::openlog(ident_.empty() ? nullptr : ident_.c_str(), syslog_option, syslog_facility);
}
~syslog_sink() override
{
::closelog();
}
~syslog_sink() override { ::closelog(); }
syslog_sink(const syslog_sink &) = delete;
syslog_sink &operator=(const syslog_sink &) = delete;
protected:
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
string_view_t payload;
memory_buf_t formatted;
if (enable_formatting_)
{
if (enable_formatting_) {
base_sink<Mutex>::formatter_->format(msg, formatted);
payload = string_view_t(formatted.data(), formatted.size());
}
else
{
} else {
payload = msg.payload;
}
size_t length = payload.size();
// limit to max int
if (length > static_cast<size_t>(std::numeric_limits<int>::max()))
{
if (length > static_cast<size_t>(std::numeric_limits<int>::max())) {
length = static_cast<size_t>(std::numeric_limits<int>::max());
}
@@ -72,38 +61,43 @@ protected:
void flush_() override {}
bool enable_formatting_ = false;
//
// Simply maps spdlog's log level to syslog priority level.
//
int syslog_prio_from_level(const details::log_msg &msg) const {
return syslog_levels_.at(static_cast<levels_array::size_type>(msg.level));
}
private:
using levels_array = std::array<int, 7>;
levels_array syslog_levels_;
// must store the ident because the man says openlog might use the pointer as
// is and not a string copy
const std::string ident_;
//
// Simply maps spdlog's log level to syslog priority level.
//
int syslog_prio_from_level(const details::log_msg &msg) const
{
return syslog_levels_.at(static_cast<levels_array::size_type>(msg.level));
}
};
using syslog_sink_mt = syslog_sink<std::mutex>;
using syslog_sink_st = syslog_sink<details::null_mutex>;
} // namespace sinks
} // namespace sinks
// Create and register a syslog logger
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> syslog_logger_mt(const std::string &logger_name, const std::string &syslog_ident = "", int syslog_option = 0,
int syslog_facility = LOG_USER, bool enable_formatting = false)
{
return Factory::template create<sinks::syslog_sink_mt>(logger_name, syslog_ident, syslog_option, syslog_facility, enable_formatting);
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> syslog_logger_mt(const std::string &logger_name,
const std::string &syslog_ident = "",
int syslog_option = 0,
int syslog_facility = LOG_USER,
bool enable_formatting = false) {
return Factory::template create<sinks::syslog_sink_mt>(logger_name, syslog_ident, syslog_option,
syslog_facility, enable_formatting);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> syslog_logger_st(const std::string &logger_name, const std::string &syslog_ident = "", int syslog_option = 0,
int syslog_facility = LOG_USER, bool enable_formatting = false)
{
return Factory::template create<sinks::syslog_sink_st>(logger_name, syslog_ident, syslog_option, syslog_facility, enable_formatting);
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> syslog_logger_st(const std::string &logger_name,
const std::string &syslog_ident = "",
int syslog_option = 0,
int syslog_facility = LOG_USER,
bool enable_formatting = false) {
return Factory::template create<sinks::syslog_sink_st>(logger_name, syslog_ident, syslog_option,
syslog_facility, enable_formatting);
}
} // namespace spdlog
} // namespace spdlog

View File

@@ -3,13 +3,14 @@
#pragma once
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/os.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/sinks/base_sink.h>
#include <array>
#ifndef SD_JOURNAL_SUPPRESS_LOCATION
# define SD_JOURNAL_SUPPRESS_LOCATION
#define SD_JOURNAL_SUPPRESS_LOCATION
#endif
#include <systemd/sd-journal.h>
@@ -19,21 +20,19 @@ namespace sinks {
/**
* Sink that write to systemd journal using the `sd_journal_send()` library call.
*/
template<typename Mutex>
class systemd_sink : public base_sink<Mutex>
{
template <typename Mutex>
class systemd_sink : public base_sink<Mutex> {
public:
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,
/* spdlog::level::err */ LOG_ERR,
/* spdlog::level::critical */ LOG_CRIT,
/* spdlog::level::off */ LOG_INFO}}
{}
: 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,
/* spdlog::level::err */ LOG_ERR,
/* spdlog::level::critical */ LOG_CRIT,
/* spdlog::level::off */ LOG_INFO}} {}
~systemd_sink() override {}
@@ -46,52 +45,55 @@ protected:
using levels_array = std::array<int, 7>;
levels_array syslog_levels_;
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
int err;
string_view_t payload;
memory_buf_t formatted;
if (enable_formatting_)
{
if (enable_formatting_) {
base_sink<Mutex>::formatter_->format(msg, formatted);
payload = string_view_t(formatted.data(), formatted.size());
}
else
{
} else {
payload = msg.payload;
}
size_t length = payload.size();
// limit to max int
if (length > static_cast<size_t>(std::numeric_limits<int>::max()))
{
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())
{
if (msg.source.empty()) {
// Note: function call inside '()' to avoid macro expansion
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), 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);
err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), payload.data(),
"PRIORITY=%d", syslog_level(msg.level),
#ifndef SPDLOG_NO_THREAD_ID
"TID=%zu", msg.thread_id,
#endif
"SYSLOG_IDENTIFIER=%.*s",
static_cast<int>(syslog_identifier.size()),
syslog_identifier.data(), nullptr);
} else {
err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), payload.data(),
"PRIORITY=%d", syslog_level(msg.level),
#ifndef SPDLOG_NO_THREAD_ID
"TID=%zu", msg.thread_id,
#endif
"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);
}
if (err)
{
if (err) {
throw_spdlog_ex("Failed writing to systemd", errno);
}
}
int syslog_level(level::level_enum l)
{
int syslog_level(level::level_enum l) {
return syslog_levels_.at(static_cast<levels_array::size_type>(l));
}
@@ -100,20 +102,20 @@ protected:
using systemd_sink_mt = systemd_sink<std::mutex>;
using systemd_sink_st = systemd_sink<details::null_mutex>;
} // namespace sinks
} // namespace sinks
// 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, const std::string &ident = "", bool enable_formatting = false)
{
template <typename Factory = spdlog::synchronous_factory>
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, ident, enable_formatting);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> systemd_logger_st(
const std::string &logger_name, const std::string &ident = "", bool enable_formatting = false)
{
template <typename Factory = spdlog::synchronous_factory>
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, ident, enable_formatting);
}
} // namespace spdlog
} // namespace spdlog

View File

@@ -4,53 +4,49 @@
#pragma once
#include <spdlog/common.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/base_sink.h>
#ifdef _WIN32
# include <spdlog/details/tcp_client-windows.h>
#include <spdlog/details/tcp_client-windows.h>
#else
# include <spdlog/details/tcp_client.h>
#include <spdlog/details/tcp_client.h>
#endif
#include <mutex>
#include <string>
#include <chrono>
#include <functional>
#include <mutex>
#include <string>
#pragma once
// Simple tcp client sink
// Connects to remote address and send the formatted log.
// Will attempt to reconnect if connection drops.
// If more complicated behaviour is needed (i.e get responses), you can inherit it and override the sink_it_ method.
// If more complicated behaviour is needed (i.e get responses), you can inherit it and override the
// sink_it_ method.
namespace spdlog {
namespace sinks {
struct tcp_sink_config
{
struct tcp_sink_config {
std::string server_host;
int server_port;
bool lazy_connect = false; // if true connect on first log call instead of on construction
bool lazy_connect = false; // if true connect on first log call instead of on construction
tcp_sink_config(std::string host, int port)
: server_host{std::move(host)}
, server_port{port}
{}
: server_host{std::move(host)},
server_port{port} {}
};
template<typename Mutex>
class tcp_sink : public spdlog::sinks::base_sink<Mutex>
{
template <typename Mutex>
class tcp_sink : public spdlog::sinks::base_sink<Mutex> {
public:
// connect to tcp host/port or throw if failed
// host can be hostname or ip address
explicit tcp_sink(tcp_sink_config sink_config)
: config_{std::move(sink_config)}
{
if (!config_.lazy_connect)
{
: config_{std::move(sink_config)} {
if (!config_.lazy_connect) {
this->client_.connect(config_.server_host, config_.server_port);
}
}
@@ -58,12 +54,10 @@ public:
~tcp_sink() override = default;
protected:
void sink_it_(const spdlog::details::log_msg &msg) override
{
void sink_it_(const spdlog::details::log_msg &msg) override {
spdlog::memory_buf_t formatted;
spdlog::sinks::base_sink<Mutex>::formatter_->format(msg, formatted);
if (!client_.is_connected())
{
if (!client_.is_connected()) {
client_.connect(config_.server_host, config_.server_port);
}
client_.send(formatted.data(), formatted.size());
@@ -77,5 +71,5 @@ protected:
using tcp_sink_mt = tcp_sink<std::mutex>;
using tcp_sink_st = tcp_sink<spdlog::details::null_mutex>;
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog

View File

@@ -4,18 +4,18 @@
#pragma once
#include <spdlog/common.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/base_sink.h>
#ifdef _WIN32
# include <spdlog/details/udp_client-windows.h>
#include <spdlog/details/udp_client-windows.h>
#else
# include <spdlog/details/udp_client.h>
#include <spdlog/details/udp_client.h>
#endif
#include <mutex>
#include <string>
#include <chrono>
#include <functional>
#include <mutex>
#include <string>
// Simple udp client sink
// Sends formatted log via udp
@@ -23,31 +23,26 @@
namespace spdlog {
namespace sinks {
struct udp_sink_config
{
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}
{}
: server_host{std::move(host)},
server_port{port} {}
};
template<typename Mutex>
class udp_sink : public spdlog::sinks::base_sink<Mutex>
{
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}
{}
: client_{sink_config.server_host, sink_config.server_port} {}
~udp_sink() override = default;
protected:
void sink_it_(const spdlog::details::log_msg &msg) override
{
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());
@@ -60,15 +55,15 @@ protected:
using udp_sink_mt = udp_sink<std::mutex>;
using udp_sink_st = udp_sink<spdlog::details::null_mutex>;
} // namespace sinks
} // 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)
{
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
} // namespace spdlog

View File

@@ -1,17 +1,20 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
// Writing to Windows Event Log requires the registry entries below to be present, with the following modifications:
// Writing to Windows Event Log requires the registry entries below to be present, with the
// following modifications:
// 1. <log_name> should be replaced with your log name (e.g. your application name)
// 2. <source_name> should be replaced with the specific source name and the key should be duplicated for
// 2. <source_name> should be replaced with the specific source name and the key should be
// duplicated for
// each source used in the application
//
// Since typically modifications of this kind require elevation, it's better to do it as a part of setup procedure.
// The snippet below uses mscoree.dll as the message file as it exists on most of the Windows systems anyway and
// happens to contain the needed resource.
// Since typically modifications of this kind require elevation, it's better to do it as a part of
// setup procedure. The snippet below uses mscoree.dll as the message file as it exists on most of
// the Windows systems anyway and happens to contain the needed resource.
//
// You can also specify a custom message file if needed.
// Please refer to Event Log functions descriptions in MSDN for more details on custom message files.
// Please refer to Event Log functions descriptions in MSDN for more details on custom message
// files.
/*---------------------------------------------------------------------------------------
@@ -47,8 +50,7 @@ namespace win_eventlog {
namespace internal {
struct local_alloc_t
{
struct local_alloc_t {
HLOCAL hlocal_;
SPDLOG_CONSTEXPR local_alloc_t() SPDLOG_NOEXCEPT : hlocal_(nullptr) {}
@@ -56,30 +58,27 @@ struct local_alloc_t
local_alloc_t(local_alloc_t const &) = delete;
local_alloc_t &operator=(local_alloc_t const &) = delete;
~local_alloc_t() SPDLOG_NOEXCEPT
{
if (hlocal_)
{
~local_alloc_t() SPDLOG_NOEXCEPT {
if (hlocal_) {
LocalFree(hlocal_);
}
}
};
/** Windows error */
struct win32_error : public spdlog_ex
{
struct win32_error : public spdlog_ex {
/** Formats an error report line: "user-message: error-code (system message)" */
static std::string format(std::string const &user_message, DWORD error_code = GetLastError())
{
static std::string format(std::string const &user_message, DWORD error_code = GetLastError()) {
std::string system_message;
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.hlocal_, 0, nullptr);
::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.hlocal_, 0, nullptr);
if (format_message_succeeded && format_message_result.hlocal_)
{
if (format_message_succeeded && format_message_result.hlocal_) {
system_message = fmt_lib::format(" ({})", (LPSTR)format_message_result.hlocal_);
}
@@ -87,23 +86,19 @@ struct win32_error : public spdlog_ex
}
explicit win32_error(std::string const &func_name, DWORD error = GetLastError())
: spdlog_ex(format(func_name, error))
{}
: spdlog_ex(format(func_name, error)) {}
};
/** Wrapper for security identifiers (SID) on Windows */
struct sid_t
{
struct sid_t {
std::vector<char> buffer_;
public:
sid_t() {}
/** creates a wrapped SID copy */
static sid_t duplicate_sid(PSID psid)
{
if (!::IsValidSid(psid))
{
static sid_t duplicate_sid(PSID psid) {
if (!::IsValidSid(psid)) {
throw_spdlog_ex("sid_t::sid_t(): invalid SID received");
}
@@ -111,8 +106,7 @@ public:
sid_t result;
result.buffer_.resize(sid_length);
if (!::CopySid(sid_length, (PSID)result.as_sid(), psid))
{
if (!::CopySid(sid_length, (PSID)result.as_sid(), psid)) {
SPDLOG_THROW(win32_error("CopySid"));
}
@@ -120,44 +114,36 @@ public:
}
/** Retrieves pointer to the internal buffer contents as SID* */
SID *as_sid() const
{
return buffer_.empty() ? nullptr : (SID *)buffer_.data();
}
SID *as_sid() const { return buffer_.empty() ? nullptr : (SID *)buffer_.data(); }
/** Get SID for the current user */
static sid_t get_current_user_sid()
{
static sid_t get_current_user_sid() {
/* create and init RAII holder for process token */
struct process_token_t
{
struct process_token_t {
HANDLE token_handle_ = INVALID_HANDLE_VALUE;
explicit process_token_t(HANDLE process)
{
if (!::OpenProcessToken(process, TOKEN_QUERY, &token_handle_))
{
explicit process_token_t(HANDLE process) {
if (!::OpenProcessToken(process, TOKEN_QUERY, &token_handle_)) {
SPDLOG_THROW(win32_error("OpenProcessToken"));
}
}
~process_token_t()
{
::CloseHandle(token_handle_);
}
~process_token_t() { ::CloseHandle(token_handle_); }
} current_process_token(::GetCurrentProcess()); // GetCurrentProcess returns pseudohandle, no leak here!
} current_process_token(
::GetCurrentProcess()); // GetCurrentProcess returns pseudohandle, no leak here!
// Get the required size, this is expected to fail with ERROR_INSUFFICIENT_BUFFER and return the token size
// Get the required size, this is expected to fail with ERROR_INSUFFICIENT_BUFFER and return
// the token size
DWORD tusize = 0;
if (::GetTokenInformation(current_process_token.token_handle_, TokenUser, NULL, 0, &tusize))
{
if (::GetTokenInformation(current_process_token.token_handle_, TokenUser, NULL, 0,
&tusize)) {
SPDLOG_THROW(win32_error("GetTokenInformation should fail"));
}
// get user token
std::vector<unsigned char> buffer(static_cast<size_t>(tusize));
if (!::GetTokenInformation(current_process_token.token_handle_, TokenUser, (LPVOID)buffer.data(), tusize, &tusize))
{
if (!::GetTokenInformation(current_process_token.token_handle_, TokenUser,
(LPVOID)buffer.data(), tusize, &tusize)) {
SPDLOG_THROW(win32_error("GetTokenInformation"));
}
@@ -166,59 +152,49 @@ public:
}
};
struct eventlog
{
static WORD get_event_type(details::log_msg const &msg)
{
switch (msg.level)
{
case level::trace:
case level::debug:
return EVENTLOG_SUCCESS;
struct eventlog {
static WORD get_event_type(details::log_msg const &msg) {
switch (msg.level) {
case level::trace:
case level::debug:
return EVENTLOG_SUCCESS;
case level::info:
return EVENTLOG_INFORMATION_TYPE;
case level::info:
return EVENTLOG_INFORMATION_TYPE;
case level::warn:
return EVENTLOG_WARNING_TYPE;
case level::warn:
return EVENTLOG_WARNING_TYPE;
case level::err:
case level::critical:
case level::off:
return EVENTLOG_ERROR_TYPE;
case level::err:
case level::critical:
case level::off:
return EVENTLOG_ERROR_TYPE;
default:
return EVENTLOG_INFORMATION_TYPE;
default:
return EVENTLOG_INFORMATION_TYPE;
}
}
static WORD get_event_category(details::log_msg const &msg)
{
return (WORD)msg.level;
}
static WORD get_event_category(details::log_msg const &msg) { return (WORD)msg.level; }
};
} // namespace internal
} // namespace internal
/*
* Windows Event Log sink
*/
template<typename Mutex>
class win_eventlog_sink : public base_sink<Mutex>
{
template <typename Mutex>
class win_eventlog_sink : public base_sink<Mutex> {
private:
HANDLE hEventLog_{NULL};
internal::sid_t current_user_sid_;
std::string source_;
WORD event_id_;
DWORD event_id_;
HANDLE event_log_handle()
{
if (!hEventLog_)
{
HANDLE event_log_handle() {
if (!hEventLog_) {
hEventLog_ = ::RegisterEventSourceA(nullptr, source_.c_str());
if (!hEventLog_ || hEventLog_ == (HANDLE)ERROR_ACCESS_DENIED)
{
if (!hEventLog_ || hEventLog_ == (HANDLE)ERROR_ACCESS_DENIED) {
SPDLOG_THROW(internal::win32_error("RegisterEventSource"));
}
}
@@ -227,8 +203,7 @@ private:
}
protected:
void sink_it_(const details::log_msg &msg) override
{
void sink_it_(const details::log_msg &msg) override {
using namespace internal;
bool succeeded;
@@ -241,16 +216,17 @@ 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)
{
if (!succeeded) {
SPDLOG_THROW(win32_error("ReportEvent"));
}
}
@@ -258,32 +234,27 @@ protected:
void flush_() override {}
public:
win_eventlog_sink(std::string const &source, WORD event_id = 1000 /* according to mscoree.dll */)
: source_(source)
, event_id_(event_id)
{
try
{
win_eventlog_sink(std::string const &source,
DWORD event_id = 1000 /* according to mscoree.dll */)
: source_(source),
event_id_(event_id) {
try {
current_user_sid_ = internal::sid_t::get_current_user_sid();
}
catch (...)
{
// get_current_user_sid() is unlikely to fail and if it does, we can still proceed without
// current_user_sid but in the event log the record will have no user name
} catch (...) {
// get_current_user_sid() is unlikely to fail and if it does, we can still proceed
// without current_user_sid but in the event log the record will have no user name
}
}
~win_eventlog_sink()
{
if (hEventLog_)
DeregisterEventSource(hEventLog_);
~win_eventlog_sink() {
if (hEventLog_) DeregisterEventSource(hEventLog_);
}
};
} // namespace win_eventlog
} // namespace win_eventlog
using win_eventlog_sink_mt = win_eventlog::win_eventlog_sink<std::mutex>;
using win_eventlog_sink_st = win_eventlog::win_eventlog_sink<details::null_mutex>;
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog

View File

@@ -4,7 +4,7 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
# include <spdlog/sinks/wincolor_sink.h>
#include <spdlog/sinks/wincolor_sink.h>
#endif
#include <spdlog/details/windows_include.h>
@@ -15,44 +15,41 @@
namespace spdlog {
namespace sinks {
template<typename ConsoleMutex>
template <typename ConsoleMutex>
SPDLOG_INLINE wincolor_sink<ConsoleMutex>::wincolor_sink(void *out_handle, color_mode mode)
: out_handle_(out_handle)
, mutex_(ConsoleMutex::mutex())
, formatter_(details::make_unique<spdlog::pattern_formatter>())
{
: out_handle_(out_handle),
mutex_(ConsoleMutex::mutex()),
formatter_(details::make_unique<spdlog::pattern_formatter>()) {
set_color_mode_impl(mode);
// set level colors
colors_[level::trace] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; // white
colors_[level::debug] = FOREGROUND_GREEN | FOREGROUND_BLUE; // cyan
colors_[level::info] = FOREGROUND_GREEN; // green
colors_[level::warn] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; // intense yellow
colors_[level::err] = FOREGROUND_RED | FOREGROUND_INTENSITY; // intense red
colors_[level::critical] =
BACKGROUND_RED | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; // intense white on red background
colors_[level::trace] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; // white
colors_[level::debug] = FOREGROUND_GREEN | FOREGROUND_BLUE; // cyan
colors_[level::info] = FOREGROUND_GREEN; // green
colors_[level::warn] =
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; // intense yellow
colors_[level::err] = FOREGROUND_RED | FOREGROUND_INTENSITY; // intense red
colors_[level::critical] = BACKGROUND_RED | FOREGROUND_RED | FOREGROUND_GREEN |
FOREGROUND_BLUE |
FOREGROUND_INTENSITY; // intense white on red background
colors_[level::off] = 0;
}
template<typename ConsoleMutex>
SPDLOG_INLINE wincolor_sink<ConsoleMutex>::~wincolor_sink()
{
template <typename ConsoleMutex>
SPDLOG_INLINE wincolor_sink<ConsoleMutex>::~wincolor_sink() {
this->flush();
}
// change the color for the given level
template<typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color(level::level_enum level, std::uint16_t color)
{
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>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::log(const details::log_msg &msg)
{
if (out_handle_ == nullptr || out_handle_ == INVALID_HANDLE_VALUE)
{
template <typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::log(const details::log_msg &msg) {
if (out_handle_ == nullptr || out_handle_ == INVALID_HANDLE_VALUE) {
return;
}
@@ -61,115 +58,106 @@ void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::log(const details::log_msg &msg)
msg.color_range_end = 0;
memory_buf_t formatted;
formatter_->format(msg, formatted);
if (should_do_colors_ && msg.color_range_end > msg.color_range_start)
{
if (should_do_colors_ && msg.color_range_end > msg.color_range_start) {
// 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);
print_range_(formatted, msg.color_range_end, formatted.size());
}
else // print without colors if color range is invalid (or color is disabled)
} else // print without colors if color range is invalid (or color is disabled)
{
write_to_file_(formatted);
}
}
template<typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::flush()
{
template <typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::flush() {
// windows console always flushed?
}
template<typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_pattern(const std::string &pattern)
{
template <typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_pattern(const std::string &pattern) {
std::lock_guard<mutex_t> lock(mutex_);
formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern));
}
template<typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter)
{
template <typename ConsoleMutex>
void SPDLOG_INLINE
wincolor_sink<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) {
std::lock_guard<mutex_t> lock(mutex_);
formatter_ = std::move(sink_formatter);
}
template<typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode(color_mode mode)
{
template <typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode(color_mode mode) {
std::lock_guard<mutex_t> lock(mutex_);
set_color_mode_impl(mode);
}
template<typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode_impl(color_mode mode)
{
if (mode == color_mode::automatic)
{
template <typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode_impl(color_mode mode) {
if (mode == color_mode::automatic) {
// should do colors only if out_handle_ points to actual console.
DWORD console_mode;
bool in_console = ::GetConsoleMode(static_cast<HANDLE>(out_handle_), &console_mode) != 0;
should_do_colors_ = in_console;
}
else
{
} else {
should_do_colors_ = mode == color_mode::always ? true : false;
}
}
// set foreground color and return the orig console attributes (for resetting later)
template<typename ConsoleMutex>
std::uint16_t SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_foreground_color_(std::uint16_t attribs)
{
template <typename ConsoleMutex>
std::uint16_t SPDLOG_INLINE
wincolor_sink<ConsoleMutex>::set_foreground_color_(std::uint16_t attribs) {
CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info;
if (!::GetConsoleScreenBufferInfo(static_cast<HANDLE>(out_handle_), &orig_buffer_info))
{
if (!::GetConsoleScreenBufferInfo(static_cast<HANDLE>(out_handle_), &orig_buffer_info)) {
// just return white if failed getting console info
return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
}
// change only the foreground bits (lowest 4 bits)
auto new_attribs = static_cast<WORD>(attribs) | (orig_buffer_info.wAttributes & 0xfff0);
auto ignored = ::SetConsoleTextAttribute(static_cast<HANDLE>(out_handle_), static_cast<WORD>(new_attribs));
auto ignored =
::SetConsoleTextAttribute(static_cast<HANDLE>(out_handle_), static_cast<WORD>(new_attribs));
(void)(ignored);
return static_cast<std::uint16_t>(orig_buffer_info.wAttributes); // return orig attribs
return static_cast<std::uint16_t>(orig_buffer_info.wAttributes); // return orig attribs
}
// print a range of formatted message to console
template<typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted, size_t start, size_t end)
{
if (end > start)
{
template <typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted,
size_t start,
size_t end) {
if (end > start) {
auto size = static_cast<DWORD>(end - start);
auto ignored = ::WriteConsoleA(static_cast<HANDLE>(out_handle_), formatted.data() + start, size, nullptr, nullptr);
auto ignored = ::WriteConsoleA(static_cast<HANDLE>(out_handle_), formatted.data() + start,
size, nullptr, nullptr);
(void)(ignored);
}
}
template<typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::write_to_file_(const memory_buf_t &formatted)
{
template <typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::write_to_file_(const memory_buf_t &formatted) {
auto size = static_cast<DWORD>(formatted.size());
DWORD bytes_written = 0;
auto ignored = ::WriteFile(static_cast<HANDLE>(out_handle_), formatted.data(), size, &bytes_written, nullptr);
auto ignored = ::WriteFile(static_cast<HANDLE>(out_handle_), formatted.data(), size,
&bytes_written, nullptr);
(void)(ignored);
}
// wincolor_stdout_sink
template<typename ConsoleMutex>
template <typename ConsoleMutex>
SPDLOG_INLINE wincolor_stdout_sink<ConsoleMutex>::wincolor_stdout_sink(color_mode mode)
: wincolor_sink<ConsoleMutex>(::GetStdHandle(STD_OUTPUT_HANDLE), mode)
{}
: wincolor_sink<ConsoleMutex>(::GetStdHandle(STD_OUTPUT_HANDLE), mode) {}
// wincolor_stderr_sink
template<typename ConsoleMutex>
template <typename ConsoleMutex>
SPDLOG_INLINE wincolor_stderr_sink<ConsoleMutex>::wincolor_stderr_sink(color_mode mode)
: wincolor_sink<ConsoleMutex>(::GetStdHandle(STD_ERROR_HANDLE), mode)
{}
} // namespace sinks
} // namespace spdlog
: wincolor_sink<ConsoleMutex>(::GetStdHandle(STD_ERROR_HANDLE), mode) {}
} // namespace sinks
} // namespace spdlog

View File

@@ -8,11 +8,11 @@
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/sink.h>
#include <array>
#include <cstdint>
#include <memory>
#include <mutex>
#include <string>
#include <array>
#include <cstdint>
namespace spdlog {
namespace sinks {
@@ -20,9 +20,8 @@ namespace sinks {
* Windows color console sink. Uses WriteConsoleA to write to the console with
* colors
*/
template<typename ConsoleMutex>
class wincolor_sink : public sink
{
template <typename ConsoleMutex>
class wincolor_sink : public sink {
public:
wincolor_sink(void *out_handle, color_mode mode);
~wincolor_sink() override;
@@ -58,16 +57,14 @@ protected:
void set_color_mode_impl(color_mode mode);
};
template<typename ConsoleMutex>
class wincolor_stdout_sink : public wincolor_sink<ConsoleMutex>
{
template <typename ConsoleMutex>
class wincolor_stdout_sink : public wincolor_sink<ConsoleMutex> {
public:
explicit wincolor_stdout_sink(color_mode mode = color_mode::automatic);
};
template<typename ConsoleMutex>
class wincolor_stderr_sink : public wincolor_sink<ConsoleMutex>
{
template <typename ConsoleMutex>
class wincolor_stderr_sink : public wincolor_sink<ConsoleMutex> {
public:
explicit wincolor_stderr_sink(color_mode mode = color_mode::automatic);
};
@@ -77,9 +74,9 @@ using wincolor_stdout_sink_st = wincolor_stdout_sink<details::console_nullmutex>
using wincolor_stderr_sink_mt = wincolor_stderr_sink<details::console_mutex>;
using wincolor_stderr_sink_st = wincolor_stderr_sink<details::console_nullmutex>;
} // namespace sinks
} // namespace spdlog
} // namespace sinks
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
# include "wincolor_sink-inl.h"
#include "wincolor_sink-inl.h"
#endif