Enable std::source_location if SPDLOG_EMIT_SOURCE_LOCATION is defined

This commit is contained in:
gabime 2023-09-15 15:49:52 +03:00
parent 1f2561c548
commit b2372fd076
4 changed files with 159 additions and 72 deletions

View File

@ -10,7 +10,7 @@
void bench_formatter(benchmark::State &state, std::string pattern) void bench_formatter(benchmark::State &state, std::string pattern)
{ {
auto formatter = spdlog::std::make_unique<spdlog::pattern_formatter>(pattern); auto formatter = std::make_unique<spdlog::pattern_formatter>(pattern);
spdlog::memory_buf_t dest; spdlog::memory_buf_t dest;
std::string logger_name = "logger-name"; std::string logger_name = "logger-name";
const char *text = "Hello. This is some message with length of 80 "; const char *text = "Hello. This is some message with length of 80 ";

View File

@ -15,9 +15,19 @@
#include <type_traits> #include <type_traits>
#include <functional> #include <functional>
#include <cstdio> #include <cstdio>
#include <cstdint>
#include <version>
# if __cpp_lib_source_location >= 201907
# include <source_location>
# define SPDLOG_STD_SOURCE_LOCATION
# elif __has_include(<experimental/source_location>)
# include <experimental/source_location>
# define SPDLOG_EXPERIMENTAL_SOURCE_LOCATION
# endif
#ifdef SPDLOG_USE_STD_FORMAT #ifdef SPDLOG_USE_STD_FORMAT
# include <version>
# if __cpp_lib_format >= 202207L # if __cpp_lib_format >= 202207L
# include <format> # include <format>
# else # else
@ -114,9 +124,7 @@ using format_string_t = std::format_string<Args...>;
using format_string_t = std::string_view; using format_string_t = std::string_view;
# endif # endif
template<class T, class Char = char>
struct is_convertible_to_basic_format_string : std::integral_constant<bool, std::is_convertible<T, std::basic_string_view<Char>>::value>
{};
# define SPDLOG_BUF_TO_STRING(x) x # define SPDLOG_BUF_TO_STRING(x) x
#else // use fmt lib instead of std::format #else // use fmt lib instead of std::format
namespace fmt_lib = fmt; namespace fmt_lib = fmt;
@ -127,20 +135,9 @@ using memory_buf_t = fmt::basic_memory_buffer<char, 250>;
template<typename... Args> template<typename... Args>
using format_string_t = fmt::format_string<Args...>; using format_string_t = fmt::format_string<Args...>;
template<class T>
using remove_cvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template<typename Char> template<typename Char>
using fmt_runtime_string = fmt::runtime_format_string<Char>; using fmt_runtime_string = fmt::runtime_format_string<Char>;
// clang doesn't like SFINAE disabled constructor in std::is_convertible<> so have to repeat the condition from basic_format_string here,
// in addition, fmt::basic_runtime<Char> is only convertible to basic_format_string<Char> but not basic_string_view<Char>
template<class T, class Char = char>
struct is_convertible_to_basic_format_string
: std::integral_constant<bool,
std::is_convertible<T, fmt::basic_string_view<Char>>::value || std::is_same<remove_cvref_t<T>, fmt_runtime_string<Char>>::value>
{};
# if defined(SPDLOG_WCHAR_FILENAMES) # if defined(SPDLOG_WCHAR_FILENAMES)
using wstring_view_t = fmt::basic_string_view<wchar_t>; using wstring_view_t = fmt::basic_string_view<wchar_t>;
using wmemory_buf_t = fmt::basic_memory_buffer<wchar_t, 250>; using wmemory_buf_t = fmt::basic_memory_buffer<wchar_t, 250>;
@ -151,11 +148,6 @@ using wformat_string_t = fmt::wformat_string<Args...>;
# define SPDLOG_BUF_TO_STRING(x) fmt::to_string(x) # define SPDLOG_BUF_TO_STRING(x) fmt::to_string(x)
#endif #endif
template<class T>
struct is_convertible_to_any_format_string : std::integral_constant<bool, is_convertible_to_basic_format_string<T, char>::value ||
is_convertible_to_basic_format_string<T, wchar_t>::value>
{};
#if defined(SPDLOG_NO_ATOMIC_LEVELS) #if defined(SPDLOG_NO_ATOMIC_LEVELS)
using level_t = details::null_atomic_int; using level_t = details::null_atomic_int;
#else #else
@ -174,6 +166,10 @@ using level_t = std::atomic<int>;
# define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO # define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
#endif #endif
// Is convertable to string_view_t ?
template <typename T>
using is_convertible_to_sv = std::enable_if_t<std::is_convertible_v<T, string_view_t>>;
// Log level enum // Log level enum
namespace level { namespace level {
enum level_enum : int enum level_enum : int
@ -255,24 +251,50 @@ private:
[[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno); [[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno);
[[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg); [[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg);
struct source_loc struct source_loc
{ {
constexpr source_loc() = default; constexpr source_loc() = default;
constexpr source_loc(const char *filename_in, int line_in, const char *funcname_in) constexpr source_loc(const char *filename_in, std::uint_least32_t line_in, const char *funcname_in)
: filename{filename_in} : filename{filename_in}
, line{line_in} , line{line_in}
, funcname{funcname_in} , funcname{funcname_in}
{} {}
constexpr bool empty() const noexcept #ifdef SPDLOG_STD_SOURCE_LOCATION
static constexpr source_loc current(const std::source_location source_location = std::source_location::current())
{
return source_loc{source_location.file_name(), source_location.line(), source_location.function_name()};
}
#elif defined(SPDLOG_EXPERIMENTAL_SOURCE_LOCATION)
static constexpr source_loc current(const std::experimental::source_location source_location = std::experimental::source_location::current())
{
return source_loc{source_location.file_name(), source_location.line(), source_location.function_name()};
}
#else // no source location support
static constexpr source_loc current()
{
return source_loc{};
}
#endif
[[nodiscard]] constexpr bool empty() const noexcept
{ {
return line == 0; return line == 0;
} }
const char *filename{nullptr}; const char *filename{nullptr};
int line{0}; std::uint_least32_t line{0};
const char *funcname{nullptr}; const char *funcname{nullptr};
}; };
struct loc_with_fmt
{
source_loc loc;
string_view_t fmt_string;
template<typename S, typename = is_convertible_to_sv<S>>
constexpr loc_with_fmt(S fmt_str, source_loc loc = source_loc::current()) noexcept: loc(loc), fmt_string(fmt_str) {}
};
struct file_event_handlers struct file_event_handlers
{ {
file_event_handlers() file_event_handlers()
@ -328,21 +350,6 @@ constexpr std::basic_string_view<T> to_string_view(std::basic_format_string<T, A
} }
#endif #endif
// make_unique support for pre c++14
// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
template<typename T, typename U, std::enable_if_t<!std::is_same<T, U>::value, int> = 0>
constexpr T conditional_static_cast(U value)
{
return static_cast<T>(value);
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, U>::value, int> = 0>
constexpr T conditional_static_cast(U value)
{
return value;
}
} // namespace details } // namespace details
} // namespace spdlog } // namespace spdlog

View File

@ -420,9 +420,9 @@ SPDLOG_INLINE int pid() noexcept
{ {
#ifdef _WIN32 #ifdef _WIN32
return conditional_static_cast<int>(::GetCurrentProcessId()); return static_cast<int>(::GetCurrentProcessId());
#else #else
return conditional_static_cast<int>(::getpid()); return static_cast<int>(::getpid());
#endif #endif
} }

View File

@ -77,14 +77,14 @@ public:
logger &operator=(logger other) noexcept; logger &operator=(logger other) noexcept;
void swap(spdlog::logger &other) noexcept; void swap(spdlog::logger &other) noexcept;
// log functions
template<typename... Args> template<typename... Args>
void log(source_loc loc, level::level_enum lvl, format_string_t<Args...> fmt, Args &&...args) void log(source_loc loc, level::level_enum lvl, format_string_t<Args...> fmt, Args &&...args)
{ {
if (should_log(lvl)) if (should_log(lvl))
{ {
log_with_format_(loc, lvl, details::to_string_view(fmt), std::forward<Args>(args)...); log_with_format_(loc, lvl, fmt, std::forward<Args>(args)...);
} }
} }
template<typename... Args> template<typename... Args>
@ -93,20 +93,36 @@ public:
log(source_loc{}, lvl, fmt, std::forward<Args>(args)...); log(source_loc{}, lvl, fmt, std::forward<Args>(args)...);
} }
template<typename T> template<typename S,
void log(level::level_enum lvl, const T &msg) typename = is_convertible_to_sv<S>,
typename... Args>
void log(source_loc loc, level::level_enum lvl, S fmt, Args &&...args)
{
if (should_log(lvl))
{
log_with_format_(loc, lvl, fmt, std::forward<Args>(args)...);
}
}
// log with no format string, just string message
template<typename S,
typename = is_convertible_to_sv<S>>
void log(source_loc loc, level::level_enum lvl, S msg)
{
if (should_log(lvl))
{
sink_it_(details::log_msg(loc, name_, lvl, msg));
}
}
template<typename S>
void log(level::level_enum lvl, S msg)
{ {
log(source_loc{}, lvl, msg); log(source_loc{}, lvl, msg);
} }
// T cannot be statically converted to format string (including string_view/wstring_view) // support for custom time
template<class T, typename std::enable_if<!is_convertible_to_any_format_string<const T &>::value, int>::type = 0> template<typename S>
void log(source_loc loc, level::level_enum lvl, const T &msg) void log(log_clock::time_point log_time, source_loc loc, level::level_enum lvl, S msg)
{
log(loc, lvl, "{}", msg);
}
void log(log_clock::time_point log_time, source_loc loc, level::level_enum lvl, string_view_t msg)
{ {
if (should_log(lvl)) if (should_log(lvl))
{ {
@ -114,19 +130,80 @@ public:
} }
} }
void log(source_loc loc, level::level_enum lvl, string_view_t msg) #ifdef SPDLOG_EMIT_SOURCE_LOCATION
template<typename... Args>
void trace(loc_with_fmt fmt, Args &&...args)
{ {
if (should_log(lvl)) log(fmt.loc, level::trace, fmt.fmt_string, std::forward<Args>(args)...);
{
sink_it_(details::log_msg(loc, name_, lvl, msg));
}
} }
void log(level::level_enum lvl, string_view_t msg) template<typename... Args>
void debug(loc_with_fmt fmt, Args &&...args)
{ {
log(source_loc{}, lvl, msg); log(fmt.loc, level::debug, fmt.fmt_string, std::forward<Args>(args)...);
} }
template<typename... Args>
void info(loc_with_fmt fmt, Args &&...args)
{
log(fmt.loc, level::info, fmt.fmt_string, std::forward<Args>(args)...);
}
template<typename... Args>
void warn(loc_with_fmt fmt, Args &&...args)
{
log(fmt.loc, level::warn, fmt.fmt_string, std::forward<Args>(args)...);
}
template<typename... Args>
void error(loc_with_fmt fmt, Args &&...args)
{
log(fmt.loc, level::err, fmt.fmt_string, std::forward<Args>(args)...);
}
template<typename... Args>
void critical(loc_with_fmt fmt, Args &&...args)
{
log(fmt.loc, level::critical, fmt.fmt_string, std::forward<Args>(args)...);
}
// log functions with no format string, just argument
template<typename S, typename = is_convertible_to_sv<S>>
void trace(const S &msg, source_loc loc = source_loc::current())
{
log(loc, level::trace, msg);
}
template<typename S, typename = is_convertible_to_sv<S>>
void debug(const S &msg, source_loc loc = source_loc::current())
{
log(loc, level::debug, msg);
}
template<typename S, typename = is_convertible_to_sv<S>>
void info(const S &msg, source_loc loc = source_loc::current())
{
log(loc, level::info, msg);
}
template<typename S, typename = is_convertible_to_sv<S>>
void warn(const S &msg, source_loc loc = source_loc::current())
{
log(loc, level::warn, msg);
}
template<typename S, typename = is_convertible_to_sv<S>>
void error(const S &msg, source_loc loc = source_loc::current())
{
log(loc, level::err, msg);
}
template<typename S, typename = is_convertible_to_sv<S>>
void critical(const S &msg, source_loc loc = source_loc::current())
{
log(loc, level::critical, msg);
}
#else
template<typename... Args> template<typename... Args>
void trace(format_string_t<Args...> fmt, Args &&...args) void trace(format_string_t<Args...> fmt, Args &&...args)
{ {
@ -163,41 +240,44 @@ public:
log(level::critical, fmt, std::forward<Args>(args)...); log(level::critical, fmt, std::forward<Args>(args)...);
} }
template<typename T> // log functions with no format string, just argument
void trace(const T &msg) template<typename S, typename = is_convertible_to_sv<S>>
void trace(const S &msg)
{ {
log(level::trace, msg); log(level::trace, msg);
} }
template<typename T> template<typename S, typename = is_convertible_to_sv<S>>
void debug(const T &msg) void debug(const S &msg)
{ {
log(level::debug, msg); log(level::debug, msg);
} }
template<typename T> template<typename S, typename = is_convertible_to_sv<S>>
void info(const T &msg) void info(const S &msg)
{ {
log(level::info, msg); log(level::info, msg);
} }
template<typename T> template<typename S, typename = is_convertible_to_sv<S>>
void warn(const T &msg) void warn(const S &msg)
{ {
log(level::warn, msg); log(level::warn, msg);
} }
template<typename T> template<typename S, typename = is_convertible_to_sv<S>>
void error(const T &msg) void error(const S &msg)
{ {
log(level::err, msg); log(level::err, msg);
} }
template<typename T> template<typename S, typename = is_convertible_to_sv<S>>
void critical(const T &msg) void critical(const S &msg)
{ {
log(level::critical, msg); log(level::critical, msg);
} }
#endif
// return true logging is enabled for the given level. // return true logging is enabled for the given level.
[[nodiscard]] bool should_log(level::level_enum msg_level) const [[nodiscard]] bool should_log(level::level_enum msg_level) const