@@ -169,3 +169,142 @@ std::string VFormat(std::string_view fmt, Args&&... args) {
169169} // namespace detail
170170
171171} // namespace iceberg
172+
173+ // / \brief Compile-time severity floor: statements below this level are removed
174+ // / entirely from the build (their format call sites and source_location literals
175+ // / are never emitted). Defaults to keeping everything. ICEBERG_LOG_FATAL is never
176+ // / gated by this floor -- its abort is always compiled in.
177+ #ifndef ICEBERG_LOG_ACTIVE_LEVEL
178+ # define ICEBERG_LOG_ACTIVE_LEVEL ::iceberg::LogLevel::kTrace
179+ #endif
180+
181+ // Internal: fixed-severity emit with compile-time floor then the authoritative
182+ // Logger::ShouldLog (the single source of truth for runtime filtering), with
183+ // formatting only on the taken path, never throwing.
184+ #define ICEBERG_INTERNAL_LOG (level_, FMT_ , ...) \
185+ do { \
186+ if constexpr ((level_) >= ICEBERG_LOG_ACTIVE_LEVEL ) { \
187+ const auto & _ib_logger = ::iceberg::detail::CurrentLogger (); \
188+ if (_ib_logger && _ib_logger->ShouldLog (level_)) { \
189+ try { \
190+ ::iceberg::detail::Emit (*_ib_logger, (level_), \
191+ ::std::source_location::current(), \
192+ ::std::format(FMT_ __VA_OPT__ (, ) __VA_ARGS__)); \
193+ } catch (...) { \
194+ ::iceberg::detail::EmitFormatError (*_ib_logger, (level_), \
195+ ::std::source_location::current()); \
196+ } \
197+ } \
198+ } \
199+ } while (0 )
200+
201+ #define ICEBERG_LOG_TRACE (...) \
202+ ICEBERG_INTERNAL_LOG (::iceberg::LogLevel::kTrace , __VA_ARGS__)
203+ #define ICEBERG_LOG_DEBUG (...) \
204+ ICEBERG_INTERNAL_LOG (::iceberg::LogLevel::kDebug , __VA_ARGS__)
205+ #define ICEBERG_LOG_INFO (...) \
206+ ICEBERG_INTERNAL_LOG (::iceberg::LogLevel::kInfo , __VA_ARGS__)
207+ #define ICEBERG_LOG_WARN (...) \
208+ ICEBERG_INTERNAL_LOG (::iceberg::LogLevel::kWarn , __VA_ARGS__)
209+ #define ICEBERG_LOG_ERROR (...) \
210+ ICEBERG_INTERNAL_LOG (::iceberg::LogLevel::kError , __VA_ARGS__)
211+ #define ICEBERG_LOG_CRITICAL (...) \
212+ ICEBERG_INTERNAL_LOG (::iceberg::LogLevel::kCritical , __VA_ARGS__)
213+
214+ // FATAL: emit if enabled (never compile-stripped), then ALWAYS flush + abort.
215+ // Acquires the default logger ONCE and uses the same instance for emit and flush
216+ // so a concurrent SetDefaultLogger cannot flush a different logger than it emitted to.
217+ #define ICEBERG_LOG_FATAL (FMT_ , ...) \
218+ do { \
219+ auto _ib_logger = ::iceberg::GetDefaultLogger (); \
220+ if (_ib_logger && _ib_logger->ShouldLog (::iceberg::LogLevel::kFatal )) { \
221+ try { \
222+ ::iceberg::detail::Emit (*_ib_logger, ::iceberg::LogLevel::kFatal , \
223+ ::std::source_location::current (), \
224+ ::std::format(FMT_ __VA_OPT__ (, ) __VA_ARGS__)); \
225+ } catch (...) { \
226+ ::iceberg::detail::EmitFormatError (*_ib_logger, ::iceberg::LogLevel::kFatal , \
227+ ::std::source_location::current ()); \
228+ } \
229+ } \
230+ if (_ib_logger) _ib_logger->Flush(); \
231+ ::std::abort (); \
232+ } while (0 )
233+
234+ // Generic, runtime-level form against the default logger. No compile-time floor
235+ // (the level is not a constant). Acquires the logger once; aborts when level == kFatal
236+ // (flushing that same logger first).
237+ #define ICEBERG_LOG (level_, FMT_ , ...) \
238+ do { \
239+ const ::iceberg::LogLevel _ib_lvl = (level_); \
240+ auto _ib_logger = ::iceberg::GetDefaultLogger (); \
241+ if (_ib_logger && _ib_logger->ShouldLog (_ib_lvl)) { \
242+ try { \
243+ ::iceberg::detail::Emit (*_ib_logger, _ib_lvl, ::std::source_location::current(), \
244+ ::std::format(FMT_ __VA_OPT__ (, ) __VA_ARGS__)); \
245+ } catch (...) { \
246+ ::iceberg::detail::EmitFormatError (*_ib_logger, _ib_lvl, \
247+ ::std::source_location::current ()); \
248+ } \
249+ } \
250+ if (_ib_lvl == ::iceberg::LogLevel::kFatal ) { \
251+ if (_ib_logger) _ib_logger->Flush (); \
252+ ::std::abort (); \
253+ } \
254+ } while (0 )
255+
256+ // Generic form targeting an EXPLICIT logger (must be an lvalue Logger&). Honors
257+ // only that logger's ShouldLog. Aborts when level == kFatal.
258+ #define ICEBERG_LOG_TO (logger_, level_, FMT_ , ...) \
259+ do { \
260+ ::iceberg::Logger& _ib_logger = (logger_); \
261+ const ::iceberg::LogLevel _ib_lvl = (level_); \
262+ if (_ib_logger.ShouldLog (_ib_lvl)) { \
263+ try { \
264+ ::iceberg::detail::Emit (_ib_logger, _ib_lvl, ::std::source_location::current(), \
265+ ::std::format(FMT_ __VA_OPT__ (, ) __VA_ARGS__)); \
266+ } catch (...) { \
267+ ::iceberg::detail::EmitFormatError (_ib_logger, _ib_lvl, \
268+ ::std::source_location::current ()); \
269+ } \
270+ } \
271+ if (_ib_lvl == ::iceberg::LogLevel::kFatal ) { \
272+ _ib_logger.Flush (); \
273+ ::std::abort (); \
274+ } \
275+ } while (0 )
276+
277+ // Runtime (non-literal) format string against the default logger. Acquires the
278+ // logger once; aborts when level == kFatal (flushing that same logger first).
279+ #define ICEBERG_LOG_RUNTIME_FMT (level_, FMT_ , ...) \
280+ do { \
281+ const ::iceberg::LogLevel _ib_lvl = (level_); \
282+ auto _ib_logger = ::iceberg::GetDefaultLogger (); \
283+ if (_ib_logger && _ib_logger->ShouldLog (_ib_lvl)) { \
284+ try { \
285+ ::iceberg::detail::Emit ( \
286+ *_ib_logger, _ib_lvl, ::std::source_location::current(), \
287+ ::iceberg::detail::VFormat((FMT_ )__VA_OPT__(, ) __VA_ARGS__)); \
288+ } catch (...) { \
289+ ::iceberg::detail::EmitFormatError (*_ib_logger, _ib_lvl, \
290+ ::std::source_location::current ()); \
291+ } \
292+ } \
293+ if (_ib_lvl == ::iceberg::LogLevel::kFatal ) { \
294+ if (_ib_logger) _ib_logger->Flush (); \
295+ ::std::abort (); \
296+ } \
297+ } while (0 )
298+
299+ // Bare, Java-style aliases. Opt-IN only (define ICEBERG_LOG_SHORT_MACROS before
300+ // including this header) to avoid colliding with glog/abseil/windows.h in
301+ // consumer translation units. No bare LOG(level) is provided.
302+ #ifdef ICEBERG_LOG_SHORT_MACROS
303+ # define LOG_TRACE (...) ICEBERG_LOG_TRACE (__VA_ARGS__)
304+ # define LOG_DEBUG (...) ICEBERG_LOG_DEBUG (__VA_ARGS__)
305+ # define LOG_INFO (...) ICEBERG_LOG_INFO (__VA_ARGS__)
306+ # define LOG_WARN (...) ICEBERG_LOG_WARN (__VA_ARGS__)
307+ # define LOG_ERROR (...) ICEBERG_LOG_ERROR (__VA_ARGS__)
308+ # define LOG_CRITICAL (...) ICEBERG_LOG_CRITICAL (__VA_ARGS__)
309+ # define LOG_FATAL (...) ICEBERG_LOG_FATAL (__VA_ARGS__)
310+ #endif // ICEBERG_LOG_SHORT_MACROS
0 commit comments