Forked from EvanLyu732/enableNetworkSinker.cmake
Last active
October 17, 2022 08:32
-
-
Save lingxd/bf752210edfb3dbe8f24c5e28114c0c0 to your computer and use it in GitHub Desktop.
spdlog.hpp.in corresponding cmake macro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Parameter: | |
# LOG MODULE: folder name | |
# BIND_PORT: network sinker register port | |
# SEND_PORT: network sinker publish port | |
macro(enable_logging LOG_MODULE BIND_PORT SEND_PORT) | |
if(NOT spdlog_FOUND) | |
find_package(spdlog REQUIRED) | |
endif() | |
if(NOT Boost_FOUND) | |
find_package(Boost REQUIRED COMPONENTS system) | |
endif() | |
set(LOG_MODULE LOG_MODULE) | |
set(BIND_PORT BIND_PORT) | |
set(SEND_PORT SEND_PORT) | |
# replace this line with your spdlog.hpp.in location. example | |
configure_file(${CMAKE_SOURCE_DIR}/include/spdlog.hpp.in ${CMAKE_SOURCE_DIR}/include/spdlog.hpp @ONLY) | |
endmacro() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
/** | |
* Goal is to provided easy to use wrapping api, for user. | |
* | |
* Mode1: color sinker, auto rotate file location | |
* Mode2: web sinker injection | |
* Mode3: stacktrace mode | |
**/ | |
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE | |
#include <spdlog/async.h> | |
#include <spdlog/common.h> | |
#include <spdlog/details/log_msg.h> | |
#include <spdlog/formatter.h> | |
#include <spdlog/pattern_formatter.h> | |
#include <spdlog/sinks/ansicolor_sink.h> | |
#include <spdlog/sinks/base_sink.h> | |
#include <spdlog/sinks/rotating_file_sink.h> | |
#include <spdlog/spdlog.h> | |
#include <array> | |
#include <boost/asio.hpp> | |
#include <boost/asio/buffer.hpp> | |
#include <boost/asio/io_service.hpp> | |
#include <boost/asio/ip/udp.hpp> | |
#include <boost/system/error_code.hpp> | |
#include <cstddef> | |
#include <cstdio> | |
#include <cstring> | |
#include <exception> | |
#include <iostream> | |
#include <memory> | |
#include <mutex> | |
#include <ostream> | |
#include <string> | |
#include <string_view> | |
#include <thread> | |
#include <utility> | |
#define LOG_MODULE "@LOG_MODULE@" | |
#define LOG_FILES_DIRS "logs/@[email protected]" | |
#define LOGGER_NAME "@LOG_MODULE@/_logger" | |
namespace ud::tools::log { | |
inline static bool is_init{false}; | |
struct Color { | |
// YELLO FOR WARNING LEVEL | |
static inline constexpr std::string_view yellow = "\x1B[38;5;226m"; | |
// RED FOR ERROR LEVEL | |
static inline constexpr std::string_view red = "\x1B[38;5;196m"; | |
// GREEN FOR INFO LEVEL | |
static inline constexpr std::string_view green = "\x1B[38;5;118m"; | |
// WHITE FOR DEBUG LEVEL | |
static inline constexpr std::string_view white = "\x1B[38;5;231m"; | |
// RESET | |
static inline constexpr std::string_view reset = "\033[0m"; | |
}; | |
struct Attributes { | |
// spdlog pattern | |
static inline constexpr char* pattern = "%^|%Y/%D/%H:%M:%S|:|%l|:|%s:%#| %v %$"; | |
// thread pool nums | |
static int inline thread_pool_nums = 2; | |
// thread pool size, 8192 by default | |
static int inline thread_pool_size = 8192; | |
// logger backtrace nums | |
static int inline backtrace_nums = 32; | |
}; | |
template<typename Mutex> | |
struct networksink : public spdlog::sinks::base_sink<Mutex> { | |
networksink(int bind_port, int send_port = 6999) : send_ep_(::boost::asio::ip::udp::endpoint(::boost::asio::ip::udp::v4(), send_port)), | |
service_(::boost::asio::io_service()), | |
socket_(::boost::asio::ip::udp::socket(service_, ::boost::asio::ip::udp::endpoint(::boost::asio::ip::udp::v4(), bind_port))) { | |
std::lock_guard<std::mutex> lock(Mutex); | |
this->formatter_ = std::make_unique<spdlog::pattern_formatter>(Attributes::pattern); | |
initialColorLevel(); | |
service_.run(); | |
} | |
~networksink() { | |
socket_.close(); | |
} | |
void initialColorLevel() { | |
colors_[spdlog::level::info] = Color::green; | |
colors_[spdlog::level::warn] = Color::yellow; | |
colors_[spdlog::level::err] = Color::red; | |
colors_[spdlog::level::debug] = Color::white; | |
colors_[spdlog::level::off] = Color::reset; | |
} | |
protected: | |
void sink_it_(const ::spdlog::details::log_msg& msg) override { | |
::spdlog::memory_buf_t formatted; | |
msg.color_range_start = 0; | |
msg.color_range_end = 0; | |
this->formatter_->format(msg, formatted); | |
auto sink_color = colors_[static_cast<size_t>(msg.level)]; | |
if (msg.color_range_end > msg.color_range_start) { | |
print_range_(formatted, 0, msg.color_range_start); | |
print_ccode_(sink_color); | |
print_range_(formatted, msg.color_range_start, msg.color_range_end); | |
print_ccode_(Color::reset.data()); | |
print_range_(formatted, msg.color_range_end, formatted.size()); | |
} else// no color | |
{ | |
print_range_(formatted, 0, formatted.size()); | |
} | |
socket_.async_send_to(::boost::asio::buffer(sink_color.data(), sink_color.size()), | |
send_ep_, | |
[this](::boost::system::error_code ec, std::size_t length) { | |
if (ec) { | |
return; | |
} | |
}); | |
socket_.async_send_to(::boost::asio::buffer(formatted.data(), formatted.size()), | |
send_ep_, | |
[this](::boost::system::error_code ec, std::size_t length) { | |
if (ec) { | |
return; | |
} | |
}); | |
} | |
void flush_() override { | |
} | |
private: | |
void print_range_(const ::spdlog::memory_buf_t& formatted, size_t start, size_t end) { | |
fwrite(formatted.data() + start, sizeof(char), (end - start), stdout); | |
} | |
void print_ccode_(const std::string& color_code) { | |
fwrite(color_code.data(), sizeof(char), color_code.size(), stdout); | |
} | |
private: | |
std::array<std::string, spdlog::level::n_levels> colors_; | |
::boost::asio::io_service service_; | |
::boost::asio::ip::udp::socket socket_; | |
::boost::asio::ip::udp::endpoint send_ep_; | |
}; | |
void initial_logger() { | |
if (!is_init) { | |
spdlog::init_thread_pool(Attributes::thread_pool_size, Attributes::thread_pool_nums); | |
using networksink_mt = networksink<std::mutex>; | |
auto network_sinks = std::make_shared<networksink_mt>(@BIND_PORT @, @SEND_PORT @); | |
auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(LOG_FILES_DIRS, 1024 * 1024 * 10, 3); | |
std::vector<spdlog::sink_ptr> sinks{network_sinks, rotating_sink}; | |
auto logger = std::make_shared<spdlog::async_logger>(LOGGER_NAME, sinks.begin(), sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block); | |
spdlog::register_logger(logger); | |
is_init = true; | |
} | |
} | |
}// namespace ud::tools::log | |
#define LOG_INFO(...) \ | |
if (ud::tools::log::is_init) { \ | |
auto logger = spdlog::get(LOGGER_NAME); \ | |
SPDLOG_LOGGER_INFO(logger, __VA_ARGS__); \ | |
} else { \ | |
initial_logger(); \ | |
} | |
#define LOG_WARN(...) \ | |
if (ud::tools::log::is_init) { \ | |
auto logger = spdlog::get(LOGGER_NAME); \ | |
SPDLOG_LOGGER_WARN(logger, __VA_ARGS__); \ | |
} else { \ | |
initial_logger(); \ | |
} | |
#define LOG_ERR(...) \ | |
if (ud::tools::log::is_init) { \ | |
auto logger = spdlog::get(LOGGER_NAME); \ | |
SPDLOG_LOGGER_ERROR(logger, __VA_ARGS__); \ | |
} else { \ | |
initial_logger(); \ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment