add loggers
This commit is contained in:
@@ -3,12 +3,42 @@ project(snipplib VERSION 0.1.0 LANGUAGES CXX)
|
||||
|
||||
option(SNPLIB_BUILD_EXAMPLES "Build examples" ON)
|
||||
|
||||
option(SNPLIB_USE_SPDLOG "Use of spdlog library" ON)
|
||||
|
||||
if(SNPLIB_USE_SPDLOG)
|
||||
find_package(spdlog CONFIG)
|
||||
if(NOT spdlog_FOUND)
|
||||
FetchContent_Declare(
|
||||
spdlog
|
||||
GIT_REPOSITORY "https://github.com/gabime/spdlog.git"
|
||||
GIT_TAG "v1.17.0"
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_SUBMODULES ""
|
||||
GIT_PROGRESS TRUE
|
||||
# CMAKE_ARGS
|
||||
# -DSPDLOG_USE_STD_FORMAT=ON
|
||||
# -DSPDLOG_FMT_EXTERNAL=OFF
|
||||
OVERRIDE_FIND_PACKAGE
|
||||
)
|
||||
|
||||
set(SPDLOG_USE_STD_FORMAT ON CACHE INTERNAL "Use of C++20 std::format")
|
||||
set(SPDLOG_FMT_EXTERNAL
|
||||
OFF
|
||||
CACHE INTERNAL
|
||||
"Turn off external fmt library"
|
||||
)
|
||||
set(SPDLOG_INSTALL ON CACHE BOOL "Enable spdlog installation" FORCE)
|
||||
FetchContent_MakeAvailable(spdlog)
|
||||
endif()
|
||||
endif(SNPLIB_USE_SPDLOG)
|
||||
|
||||
set(LIB_HEADERS
|
||||
include/snipplib/concepts/snplib_concepts.h
|
||||
include/snipplib/concepts/snplib_traits.h
|
||||
include/snipplib/utils/snplib_hash.h
|
||||
include/snipplib/utils/snplib_string.h
|
||||
include/snipplib/utils/snplib_keyvalue_expr.h
|
||||
include/snipplib/utils/snplib_logger.h
|
||||
include/snipplib/utils/snplib_utils.h
|
||||
include/snipplib/containers/snplib_hmap.h
|
||||
include/snipplib/containers/snplib_hvec.h
|
||||
@@ -24,6 +54,16 @@ target_include_directories(
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>"
|
||||
)
|
||||
if(SNPLIB_USE_SPDLOG)
|
||||
target_compile_definitions(
|
||||
${PROJECT_NAME}
|
||||
INTERFACE
|
||||
SPDLOG_USE_STD_FORMAT=1
|
||||
SPDLOG_FMT_EXTERNAL=0
|
||||
SNPLIB_SPDLOGGER=1
|
||||
)
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE spdlog::spdlog_header_only)
|
||||
endif()
|
||||
|
||||
if(SNPLIB_BUILD_EXAMPLES)
|
||||
set(EXAM_STRING str_exam)
|
||||
|
||||
@@ -200,4 +200,18 @@ template <typename T, typename UT = void>
|
||||
concept snplib_async_retval_c = snplib_awaitable_c<T, UT> && snplib_expected_c<UT>;
|
||||
|
||||
|
||||
|
||||
/* a concept for generic logger class */
|
||||
|
||||
template <typename T>
|
||||
concept snplib_logger_c = requires(T t) {
|
||||
{ t.logInfo(std::declval<std::string const&>()) };
|
||||
{ t.logWarn(std::declval<std::string const&>()) };
|
||||
{ t.logDebug(std::declval<std::string const&>()) };
|
||||
{ t.logError(std::declval<std::string const&>()) };
|
||||
{ t.logTrace(std::declval<std::string const&>()) };
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace snplib
|
||||
@@ -81,4 +81,5 @@ struct snplib_func_traits_t<F&&> : snplib_func_traits_t<F> {
|
||||
template <typename T>
|
||||
using snplib_func_arg1_t = typename snplib_func_traits_t<T>::arg1_t;
|
||||
|
||||
|
||||
} // namespace snplib
|
||||
222
include/snipplib/utils/snplib_logger.h
Normal file
222
include/snipplib/utils/snplib_logger.h
Normal file
@@ -0,0 +1,222 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#ifdef SNPLIB_SPDLOGGER
|
||||
#include <spdlog/logger.h>
|
||||
#endif
|
||||
|
||||
#include "../concepts/snplib_concepts.h"
|
||||
|
||||
namespace snplib
|
||||
{
|
||||
|
||||
/* snplib_logger_c-like class adaptor to use formating */
|
||||
|
||||
// template <snplib_logger_c LoggerT>
|
||||
// struct snplib_logger_fmt_adaptor_t : public LoggerT {
|
||||
// template<typename ...CtorArgTs>
|
||||
// snplib_logger_fmt_adaptor_t(CtorArgTs&&... ctor_args): LoggerT(std::forward<CtorArgTs>(ctor_args)...) {}
|
||||
|
||||
// ~snplib_logger_fmt_adaptor_t() = default;
|
||||
|
||||
// template <std::formattable<char>... ArgTs>
|
||||
// auto logInfo(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||
// {
|
||||
// return logInfo(std::format(fmt, std::forward<ArgTs>(args)...));
|
||||
// }
|
||||
|
||||
// template <std::formattable<char>... ArgTs>
|
||||
// auto logWarn(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||
// {
|
||||
// return logWarn(std::format(fmt, std::forward<ArgTs>(args)...));
|
||||
// }
|
||||
|
||||
// template <std::formattable<char>... ArgTs>
|
||||
// auto logDebug(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||
// {
|
||||
// return logDebug(std::format(fmt, std::forward<ArgTs>(args)...));
|
||||
// }
|
||||
|
||||
// template <std::formattable<char>... ArgTs>
|
||||
// auto logError(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||
// {
|
||||
// return logError(std::format(fmt, std::forward<ArgTs>(args)...));
|
||||
// }
|
||||
|
||||
// template <std::formattable<char>... ArgTs>
|
||||
// auto logTrace(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||
// {
|
||||
// return logTrace(std::format(fmt, std::forward<ArgTs>(args)...));
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
|
||||
/* a NULL-logger */
|
||||
|
||||
struct snplib_null_logger_t {
|
||||
void logInfo(std::string const&) {}
|
||||
void logWarn(std::string const&) {}
|
||||
void logDebug(std::string const&) {}
|
||||
void logError(std::string const&) {}
|
||||
void logTrace(std::string const&) {}
|
||||
};
|
||||
|
||||
|
||||
#ifdef SNPLIB_SPDLOGGER
|
||||
|
||||
/* SPDLOG-library based advanced single/multithreaded logger */
|
||||
|
||||
class snplib_spdlog_logger_t
|
||||
{
|
||||
protected:
|
||||
std::shared_ptr<spdlog::logger> _loggerSPtr;
|
||||
std::list<std::string> _currentLogPatternRange{};
|
||||
std::string _currentLogPattern{};
|
||||
|
||||
public:
|
||||
// [year-month-day time.millisecs][log-level]: log-message
|
||||
constexpr static std::array LOGGER_DEFAULT_FORMAT = {std::string_view{"[%Y-%m-%d %T.%e]"}, std::string_view{"[%l]"},
|
||||
std::string_view{": "}, std::string_view{"%v"}};
|
||||
|
||||
|
||||
|
||||
template <std::ranges::input_range R = decltype(LOGGER_DEFAULT_FORMAT)>
|
||||
requires snplib_input_char_range_c<std::ranges::range_value_t<R>>
|
||||
snplib_spdlog_logger_t(std::shared_ptr<spdlog::logger> logger, R&& pattern_range = LOGGER_DEFAULT_FORMAT)
|
||||
: _loggerSPtr(logger)
|
||||
{
|
||||
if (std::distance(pattern_range.begin(), pattern_range.end())) {
|
||||
std::ranges::copy(
|
||||
pattern_range | std::views::transform([](const auto& el) { return std::string(el.begin(), el.end()); }),
|
||||
std::back_inserter(_currentLogPatternRange));
|
||||
} else {
|
||||
std::ranges::copy(LOGGER_DEFAULT_FORMAT | std::views::transform([](const auto& el) {
|
||||
return std::string(el.begin(), el.end());
|
||||
}),
|
||||
std::back_inserter(_currentLogPatternRange));
|
||||
}
|
||||
|
||||
std::ranges::copy(std::views::join(_currentLogPatternRange), std::back_inserter(_currentLogPattern));
|
||||
|
||||
_loggerSPtr->set_pattern(_currentLogPattern);
|
||||
}
|
||||
|
||||
virtual ~snplib_spdlog_logger_t() = default;
|
||||
|
||||
void logMessage(spdlog::level::level_enum level, const std::string& msg)
|
||||
{
|
||||
_loggerSPtr->log(level, msg);
|
||||
}
|
||||
|
||||
// specialized for given level methods
|
||||
|
||||
void logCritical(const std::string& msg)
|
||||
{
|
||||
logMessage(spdlog::level::critical, msg);
|
||||
}
|
||||
|
||||
void logError(const std::string& msg)
|
||||
{
|
||||
logMessage(spdlog::level::err, msg);
|
||||
}
|
||||
|
||||
void logWarn(const std::string& msg)
|
||||
{
|
||||
logMessage(spdlog::level::warn, msg);
|
||||
}
|
||||
|
||||
void logInfo(const std::string& msg)
|
||||
{
|
||||
logMessage(spdlog::level::info, msg);
|
||||
}
|
||||
|
||||
void logDebug(const std::string& msg)
|
||||
{
|
||||
logMessage(spdlog::level::debug, msg);
|
||||
}
|
||||
|
||||
void logTrace(const std::string& msg)
|
||||
{
|
||||
logMessage(spdlog::level::trace, msg);
|
||||
}
|
||||
|
||||
template <std::formattable<char>... ArgTs>
|
||||
void logMessage(spdlog::level::level_enum level, spdlog::format_string_t<ArgTs...> fmt, ArgTs&&... args)
|
||||
{
|
||||
_loggerSPtr->log(level, fmt, std::forward<ArgTs>(args)...);
|
||||
}
|
||||
|
||||
template <std::formattable<char>... ArgTs>
|
||||
void logCritical(spdlog::format_string_t<ArgTs...> fmt, ArgTs&&... args)
|
||||
{
|
||||
_loggerSPtr->log(spdlog::level::critical, fmt, std::forward<ArgTs>(args)...);
|
||||
}
|
||||
|
||||
template <std::formattable<char>... ArgTs>
|
||||
void logError(spdlog::format_string_t<ArgTs...> fmt, ArgTs&&... args)
|
||||
{
|
||||
_loggerSPtr->log(spdlog::level::err, fmt, std::forward<ArgTs>(args)...);
|
||||
}
|
||||
|
||||
template <std::formattable<char>... ArgTs>
|
||||
void logWarn(spdlog::format_string_t<ArgTs...> fmt, ArgTs&&... args)
|
||||
{
|
||||
_loggerSPtr->log(spdlog::level::warn, fmt, std::forward<ArgTs>(args)...);
|
||||
}
|
||||
|
||||
template <std::formattable<char>... ArgTs>
|
||||
void logInfo(spdlog::format_string_t<ArgTs...> fmt, ArgTs&&... args)
|
||||
{
|
||||
_loggerSPtr->log(spdlog::level::info, fmt, std::forward<ArgTs>(args)...);
|
||||
}
|
||||
|
||||
template <std::formattable<char>... ArgTs>
|
||||
void logDebug(spdlog::format_string_t<ArgTs...> fmt, ArgTs&&... args)
|
||||
{
|
||||
_loggerSPtr->log(spdlog::level::debug, fmt, std::forward<ArgTs>(args)...);
|
||||
}
|
||||
|
||||
template <std::formattable<char>... ArgTs>
|
||||
void logTrace(spdlog::format_string_t<ArgTs...> fmt, ArgTs&&... args)
|
||||
{
|
||||
_loggerSPtr->log(spdlog::level::trace, fmt, std::forward<ArgTs>(args)...);
|
||||
}
|
||||
|
||||
|
||||
// 'after_idx' is 0-based index!
|
||||
void addMarkToPatternIdx(snplib_input_char_range_c auto&& mark, size_t after_idx = 1)
|
||||
requires(!std::is_pointer_v<std::decay_t<decltype(mark)>>)
|
||||
{
|
||||
if constexpr (std::is_pointer_v<std::decay_t<decltype(mark)>>) {
|
||||
addMarkToPatternIdx(std::string_view(mark), after_idx);
|
||||
} else {
|
||||
if (!std::distance(mark.begin(), mark.end())) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = _currentLogPatternRange.begin();
|
||||
size_t idx = 0;
|
||||
while (it != _currentLogPatternRange.end()) {
|
||||
++it;
|
||||
if (idx == after_idx)
|
||||
break;
|
||||
|
||||
++idx;
|
||||
}
|
||||
|
||||
_currentLogPatternRange.emplace(it, mark.begin(), mark.end());
|
||||
|
||||
_currentLogPattern.clear();
|
||||
std::ranges::copy(std::views::join(_currentLogPatternRange), std::back_inserter(_currentLogPattern));
|
||||
|
||||
_loggerSPtr->set_pattern(_currentLogPattern);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(snplib_logger_c<snplib_spdlog_logger_t>);
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace snplib
|
||||
@@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "snplib_hash.h"
|
||||
#include "snplib_string.h"
|
||||
#include "snplib_keyvalue_expr.h"
|
||||
#include "snplib_logger.h"
|
||||
#include "snplib_string.h"
|
||||
|
||||
Reference in New Issue
Block a user