33#include <source_location>
41namespace iceberg::internal {
49template <
typename... Args>
50std::string
VFormat(std::string_view fmt, Args&&... args) {
51 auto store = std::make_format_args(args...);
52 return std::vformat(fmt, store);
61template <
typename MakeMessage>
63 MakeMessage&& make_message)
noexcept {
64 if (!logger.ShouldLog(level))
return;
66 Emit(logger, level, location, std::forward<MakeMessage>(make_message)());
68 EmitFormatError(logger, level, location);
73template <
typename MakeMessage>
75 MakeMessage&& make_message)
noexcept {
76 const std::shared_ptr<Logger>& logger = CurrentLogger();
78 EmitIfEnabled(*logger, level, location, std::forward<MakeMessage>(make_message));
86template <
typename MakeMessage>
88 MakeMessage&& make_message)
noexcept {
91 message = std::forward<MakeMessage>(make_message)();
93 message =
"<fmt error>";
95 if (logger !=
nullptr) {
96 if (logger->ShouldLog(LogLevel::kFatal)) {
97 Emit(*logger, LogLevel::kFatal, location, std::string(message));
103 handler(location, message);
110template <
typename MakeMessage>
111void LogToCurrentRuntime(
LogLevel level,
const std::source_location& location,
112 MakeMessage&& make_message)
noexcept {
113 const std::shared_ptr<Logger>& logger = CurrentLogger();
114 if (level == LogLevel::kFatal) {
115 DispatchFatal(logger.get(), location, std::forward<MakeMessage>(make_message));
118 EmitIfEnabled(*logger, level, location, std::forward<MakeMessage>(make_message));
122template <
typename MakeMessage>
123void LogToExplicitRuntime(Logger& logger,
LogLevel level,
124 const std::source_location& location,
125 MakeMessage&& make_message)
noexcept {
126 if (level == LogLevel::kFatal) {
127 DispatchFatal(&logger, location, std::forward<MakeMessage>(make_message));
129 EmitIfEnabled(logger, level, location, std::forward<MakeMessage>(make_message));
132template <
typename MakeMessage>
133[[noreturn]]
void LogFatal(
const std::source_location& location,
134 MakeMessage&& make_message)
noexcept {
136 DispatchFatal(logger.get(), location, std::forward<MakeMessage>(make_message));
183#ifndef ICEBERG_LOG_ACTIVE_LEVEL
184# define ICEBERG_LOG_ACTIVE_LEVEL ::iceberg::LogLevel::kTrace
189#define ICEBERG_INTERNAL_LOG_MESSAGE(FMT_, ...) \
190 [&]() -> ::std::string { return ::std::format((FMT_)__VA_OPT__(, ) __VA_ARGS__); }
194#define ICEBERG_INTERNAL_LOG(level_, FMT_, ...) \
196 if constexpr ((level_) >= ICEBERG_LOG_ACTIVE_LEVEL) { \
197 ::iceberg::internal::LogToCurrent( \
198 (level_), ::std::source_location::current(), \
199 ICEBERG_INTERNAL_LOG_MESSAGE(FMT_ __VA_OPT__(, ) __VA_ARGS__)); \
203#define ICEBERG_LOG_TRACE(...) \
204 ICEBERG_INTERNAL_LOG(::iceberg::LogLevel::kTrace, __VA_ARGS__)
205#define ICEBERG_LOG_DEBUG(...) \
206 ICEBERG_INTERNAL_LOG(::iceberg::LogLevel::kDebug, __VA_ARGS__)
207#define ICEBERG_LOG_INFO(...) \
208 ICEBERG_INTERNAL_LOG(::iceberg::LogLevel::kInfo, __VA_ARGS__)
209#define ICEBERG_LOG_WARN(...) \
210 ICEBERG_INTERNAL_LOG(::iceberg::LogLevel::kWarn, __VA_ARGS__)
211#define ICEBERG_LOG_ERROR(...) \
212 ICEBERG_INTERNAL_LOG(::iceberg::LogLevel::kError, __VA_ARGS__)
213#define ICEBERG_LOG_CRITICAL(...) \
214 ICEBERG_INTERNAL_LOG(::iceberg::LogLevel::kCritical, __VA_ARGS__)
219#define ICEBERG_LOG_FATAL(FMT_, ...) \
220 ::iceberg::internal::LogFatal( \
221 ::std::source_location::current(), \
222 ICEBERG_INTERNAL_LOG_MESSAGE(FMT_ __VA_OPT__(, ) __VA_ARGS__))
226#define ICEBERG_LOG(level_, FMT_, ...) \
227 ::iceberg::internal::LogToCurrentRuntime( \
228 (level_), ::std::source_location::current(), \
229 ICEBERG_INTERNAL_LOG_MESSAGE(FMT_ __VA_OPT__(, ) __VA_ARGS__))
233#define ICEBERG_LOG_TO(logger_, level_, FMT_, ...) \
234 ::iceberg::internal::LogToExplicitRuntime( \
235 (logger_), (level_), ::std::source_location::current(), \
236 ICEBERG_INTERNAL_LOG_MESSAGE(FMT_ __VA_OPT__(, ) __VA_ARGS__))
240#define ICEBERG_LOG_RUNTIME_FMT(level_, FMT_, ...) \
241 ::iceberg::internal::LogToCurrentRuntime( \
242 (level_), ::std::source_location::current(), [&]() -> ::std::string { \
243 return ::iceberg::internal::VFormat((FMT_)__VA_OPT__(, ) __VA_ARGS__); \
Pluggable logging sink.
Definition logger.h:146
Severity levels for the logging system.
void LogToCurrent(LogLevel level, const std::source_location &location, MakeMessage &&make_message) noexcept
Emit to the current (scoped-or-default) logger if enabled.
Definition log_macros.h:74
std::string VFormat(std::string_view fmt, Args &&... args)
Runtime (non-literal) format-string helper for ICEBERG_LOG_RUNTIME_FMT.
Definition log_macros.h:50
void EmitIfEnabled(Logger &logger, LogLevel level, const std::source_location &location, MakeMessage &&make_message) noexcept
Gate on logger.ShouldLog, then format (via make_message) and emit.
Definition log_macros.h:62
void DispatchFatal(Logger *logger, const std::source_location &location, MakeMessage &&make_message) noexcept
Format once, emit if enabled, flush, run the fatal handler, and abort.
Definition log_macros.h:87
Pluggable logging interface and the process-global default logger.
ICEBERG_EXPORT FatalHandler GetFatalHandler()
Return the installed fatal handler (empty if none). Used by the fatal logging path; thread-safe.
ICEBERG_EXPORT std::shared_ptr< Logger > GetCurrentLogger()
Return the effective logger for this thread (never null): the active ScopedLogger binding if any,...
LogLevel
Logging severity level, ordered from most to least verbose.
Definition log_level.h:38