1#ifndef LIBSBX_UTILITY_LOGGER_HPP_
2#define LIBSBX_UTILITY_LOGGER_HPP_
10#include <fmt/format.h>
12#include <spdlog/logger.h>
13#include <spdlog/sinks/stdout_color_sinks.h>
14#include <spdlog/sinks/basic_file_sink.h>
15#include <spdlog/sinks/base_sink.h>
17#include <libsbx/utility/target.hpp>
18#include <libsbx/utility/string_literal.hpp>
20namespace sbx::utility {
24template<
typename Mutex>
27 using base = spdlog::sinks::base_sink<Mutex>;
33 spdlog::level::level_enum level;
37 : _max_lines{max_lines} {}
39 [[nodiscard]]
auto lines() -> std::vector<log_line> {
40 auto lock = std::lock_guard<Mutex>{base::mutex_};
42 return {_lines.begin(), _lines.end()};
46 std::lock_guard<Mutex> lock(base::mutex_);
53 void sink_it_(
const spdlog::details::log_msg& msg)
override {
54 spdlog::memory_buf_t formatted;
55 base::formatter_->format(msg, formatted);
57 auto lock = std::lock_guard<Mutex>{base::mutex_};
58 _lines.emplace_back(fmt::to_string(formatted), msg.level);
60 if (_lines.size() > _max_lines) {
65 void flush_()
override {
71 std::size_t _max_lines;
72 std::deque<log_line> _lines;
76using ring_buffer_sink_mt = ring_buffer_sink<std::mutex>;
77using ring_buffer_sink_st = ring_buffer_sink<spdlog::details::null_mutex>;
81 static auto create_logger() -> spdlog::logger {
82 auto sinks = std::vector<std::shared_ptr<spdlog::sinks::sink>>{};
84 sinks.push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(
"./demo/logs/sbx.log",
true));
86 if constexpr (utility::build_configuration_v == utility::build_configuration::debug) {
87 sinks.push_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
90 sink = std::make_shared<ring_buffer_sink_st>();
92 sinks.push_back(sink);
94 auto logger = spdlog::logger{
"logger", std::begin(sinks), std::end(sinks)};
96 logger.set_pattern(
"[%Y-%m-%d %H:%M:%S] [%^%l%$] %v");
98 if constexpr (build_configuration_v == build_configuration::debug) {
99 logger.set_level(spdlog::level::debug);
101 logger.set_level(spdlog::level::info);
107 inline static auto sink = std::shared_ptr<ring_buffer_sink_st>{};
108 inline static auto logger = create_logger();
112inline auto instance() -> spdlog::logger& {
113 return logger_instance::logger;
116inline auto sink() -> std::shared_ptr<ring_buffer_sink_st>& {
117 return logger_instance::sink;
122template<
string_literal Tag>
127 template<
typename... Args>
128 using format_string_type = spdlog::format_string_t<Args...>;
134 template<
typename... Args>
135 static auto trace(format_string_type<Args...> format, Args&&... args) ->
void {
137 if constexpr (utility::build_configuration_v == utility::build_configuration::debug) {
138 detail::instance().trace(
"[{}] : {}", Tag, fmt::format(format, std::forward<Args>(args)...));
142 template<
typename Type>
143 static auto trace(
const Type& value) ->
void {
144 if constexpr (utility::build_configuration_v == utility::build_configuration::debug) {
145 detail::instance().trace(
"[{}] : {}", Tag, value);
149 template<
typename... Args>
150 static auto debug(format_string_type<Args...> format, Args&&... args) ->
void {
151 if constexpr (utility::build_configuration_v == utility::build_configuration::debug) {
152 detail::instance().debug(
"[{}] : {}", Tag, fmt::format(format, std::forward<Args>(args)...));
156 template<
typename Type>
157 static auto debug(
const Type& value) ->
void {
158 if constexpr (utility::build_configuration_v == utility::build_configuration::debug) {
159 detail::instance().debug(
"[{}] : {}", Tag, value);
163 template<
typename... Args>
164 static auto info(format_string_type<Args...> format, Args&&... args) ->
void {
165 detail::instance().info(
"[{}] : {}", Tag, fmt::format(format, std::forward<Args>(args)...));
168 template<
typename Type>
169 static auto info(
const Type& value) ->
void {
170 detail::instance().info(
"[{}] : {}", Tag, value);
173 template<
typename... Args>
174 static auto warn(format_string_type<Args...> format, Args&&... args) ->
void {
175 detail::instance().warn(
"[{}] : {}", Tag, fmt::format(format, std::forward<Args>(args)...));
178 template<
typename Type>
179 static auto warn(
const Type& value) ->
void {
180 detail::instance().warn(
"[{}] : {}", Tag, value);
183 template<
typename... Args>
184 static auto error(format_string_type<Args...> format, Args&&... args) ->
void {
185 detail::instance().error(
"[{}] : {}", Tag, fmt::format(format, std::forward<Args>(args)...));
188 template<
typename Type>
189 static auto error(
const Type& value) ->
void {
190 detail::instance().error(
"[{}] : {}", Tag, value);
193 template<
typename... Args>
194 static auto critical(format_string_type<Args...> format, Args&&... args) ->
void {
195 detail::instance().critical(
"[{}] : {}", Tag, fmt::format(format, std::forward<Args>(args)...));
198 template<
typename Type>
199 static auto critical(
const Type& value) ->
void {
200 detail::instance().critical(
"[{}] : {}", Tag, value);
208template<
typename Type>
209requires (std::is_enum_v<Type>)
210struct fmt::formatter<Type> :
public fmt::formatter<std::underlying_type_t<Type>> {
212 using base_type = fmt::formatter<std::underlying_type_t<Type>>;
214 template<
typename FormatContext>
215 auto format(
const Type& value, FormatContext& context) ->
decltype(
auto) {
216 return base_type::format(
static_cast<std::underlying_type_t<Type>
>(value), context);
222template<
typename Type>
223struct fmt::formatter<std::optional<Type>> :
public fmt::formatter<Type> {
227 template<
typename FormatContext>
228 auto format(
const std::optional<Type>& value, FormatContext& context) ->
decltype(
auto) {
230 return base_type::format(*value, context);
233 return fmt::format_to(context.out(),
"[empty optional]");
239struct fmt::formatter<std::filesystem::path> :
public fmt::formatter<std::filesystem::path::string_type> {
241 using base_type = fmt::formatter<std::filesystem::path::string_type>;
243 template<
typename FormatContext>
244 auto format(
const std::filesystem::path& value, FormatContext& context) ->
decltype(
auto) {
245 return fmt::format_to(context.out(),
"{}", value.string());
Definition: logger.hpp:25
Definition: logger.hpp:123
Definition: logger.hpp:79
Definition: logger.hpp:31