mirror of
https://github.com/gabime/spdlog.git
synced 2024-12-26 10:31:34 +08:00
Enable std::source_location if SPDLOG_EMIT_SOURCE_LOCATION is defined
This commit is contained in:
parent
1f2561c548
commit
b2372fd076
@ -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 ";
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user