Skip to content

feat(logging): add Loggers registry (6/6) - #737

Open
kamcheungting-db wants to merge 2 commits into
apache:mainfrom
kamcheungting-db:logging-block6-registry
Open

feat(logging): add Loggers registry (6/6)#737
kamcheungting-db wants to merge 2 commits into
apache:mainfrom
kamcheungting-db:logging-block6-registry

Conversation

@kamcheungting-db

@kamcheungting-dbkamcheungting-db commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Part 6 of the logging stack (builds on #726). Completes the system with configuration-driven backend selection, mirroring MetricsReporters.

What's here

  • Loggers::Register(type, factory) registers a named backend; Loggers::Load(properties) builds one, choosing the type from the logger-impl property.
  • Built-ins: noop, cerr, and (when built with spdlog) spdlog. With no logger-impl set, the default is spdlog when compiled in, else cerr — i.e. logs by default.
  • Loggers::LoadAndSetDefault(properties) builds a logger and installs it as the process default.

End-to-end testslogging_end_to_end_test drives the public surface the way an app does: configure a backend + level via properties, install it, log through the macros, and check the real output. Also covers the compiled-in default backend and a macro reaching a real spdlog sink. clang/libc++, spdlog ON and OFF.

This pull request and its description were written by Isaac.

@kamcheungting-db
kamcheungting-dbforce-pushed the logging-block6-registry branch 15 times, most recently from 19003d8 to 51e997bCompareJune 22, 2026 10:24
@kamcheungting-db
kamcheungting-dbforce-pushed the logging-block6-registry branch 6 times, most recently from faed95d to d0066d4CompareJune 24, 2026 18:39
@kamcheungting-db
kamcheungting-dbforce-pushed the logging-block6-registry branch 2 times, most recently from 49a68c1 to b68bd93CompareJune 30, 2026 20:37
@manuzhang

Copy link
Copy Markdown
Member

@kamcheungting-db can you please rebase your PR?

@kamcheungting-db
kamcheungting-dbforce-pushed the logging-block6-registry branch 5 times, most recently from 8d4515e to aaa1ebfCompareJuly 16, 2026 07:21

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR completes the logging stack by adding a configuration-driven Loggers registry/factory (mirroring MetricsReporters), installing a process-default logger selected by properties, and introducing public ICEBERG_LOG_* macros (plus opt-in bare LOG_* aliases) with end-to-end and unit test coverage across spdlog-on/off builds.

Changes:

  • Added Loggers::{Register, Load, LoadAndSetDefault} with built-in backends (noop, cerr, and spdlog when compiled in) and a compiled-backend default.
  • Introduced iceberg/logging/log_macros.h (and short_log_macros.h) plus a FatalHandler hook for fatal logging.
  • Added comprehensive tests (macros behavior, registry behavior, spdlog backend, and end-to-end logging output), and wired builds (CMake + Meson) including MSVC /Zc:preprocessor for __VA_OPT__.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/iceberg/test/spdlog_logger_test.ccAdds unit tests for the spdlog-backed logger implementation.
src/iceberg/test/meson.buildRegisters new logging-related tests in Meson.
src/iceberg/test/macros_test.ccAdds runtime behavior + death tests for logging macros (formatting, gating, fatal semantics, handler).
src/iceberg/test/macros_active_level_test.ccTests compile-time active-level stripping behavior.
src/iceberg/test/logging_end_to_end_test.ccEnd-to-end validation of registry/config/default/macro integration and real output.
src/iceberg/test/loggers_test.ccAdds unit tests for the Loggers registry and property handling.
src/iceberg/test/CMakeLists.txtEnables MSVC conforming preprocessor for tests; adds new test sources.
src/iceberg/meson.buildAdds logging sources (including registry + spdlog backend) to Meson build.
src/iceberg/logging/short_log_macros.hProvides opt-in bare LOG_* aliases for ICEBERG_LOG_*.
src/iceberg/logging/meson.buildInstalls new public logging headers; generates Meson-only config.h.
src/iceberg/logging/loggers.hDeclares the public Loggers registry/factory API and property keys.
src/iceberg/logging/loggers.ccImplements the registry, built-in factories, and load/initialize semantics.
src/iceberg/logging/logger.hExtends logging API docs; adds FatalHandler API surface.
src/iceberg/logging/logger.ccImplements compiled-backend default selection and fatal handler storage/access.
src/iceberg/logging/log_macros.hAdds the ICEBERG_LOG_* macro layer and supporting helpers.
src/iceberg/logging/internal/spdlog_logger.hIntroduces internal spdlog-backed SpdLogger sink.
src/iceberg/logging/internal/spdlog_logger.ccImplements spdlog sink behavior including pattern support and level mapping.
src/iceberg/logging/config.h.inAdds generated build-time logging backend configuration header template.
src/iceberg/CMakeLists.txtGenerates config.h; gates spdlog compilation/link; exports /Zc:preprocessor for consumers.
meson.buildEnables /Zc:preprocessor via Meson supported-args on MSVC.
CMakeLists.txtAdds ICEBERG_SPDLOG option.
cmake_modules/IcebergThirdpartyToolchain.cmakeGates spdlog dependency resolution behind ICEBERG_SPDLOG.

Comment on lines +82 to +95
/// \brief Runtime-level variant against the current logger: emit if enabled, then
/// flush + abort when level == kFatal (using the same acquired logger).
template <typename MakeMessage>
void LogToCurrentRuntime(LogLevel level, const std::source_location& location,
MakeMessage&& make_message) noexcept {
const std::shared_ptr<Logger>& logger = CurrentLogger();
if (logger) {
EmitIfEnabled(*logger, level, location, std::forward<MakeMessage>(make_message));
}
if (level == LogLevel::kFatal) {
if (logger) logger->Flush();
std::abort();
}
}
Comment on lines +97 to +108
/// \brief Runtime-level variant against an explicit logger: emit if enabled, then
/// flush + abort when level == kFatal.
template <typename MakeMessage>
void LogToExplicitRuntime(Logger& logger, LogLevel level,
const std::source_location& location,
MakeMessage&& make_message) noexcept {
EmitIfEnabled(logger, level, location, std::forward<MakeMessage>(make_message));
if (level == LogLevel::kFatal) {
logger.Flush();
std::abort();
}
}
Comment on lines +74 to +79
SpdLogger::SpdLogger(std::shared_ptr<spdlog::logger> logger, LogLevel level)
: logger_(std::move(logger)), level_(level) {
if (logger_) {
logger_->set_level(spdlog::level::trace); // filtering is done by ShouldLog
}
}
@kamcheungting-db
kamcheungting-dbforce-pushed the logging-block6-registry branch 4 times, most recently from 865f93f to 6ad0e68CompareAugust 6, 2026 01:05
Fifth block: the default production backend and the build option that selects it.
- SpdLogger wraps spdlog::logger (kCritical/kFatal -> spdlog critical, others 1:1),
forwarding the pre-formatted message and source location. Synchronous only in
v1 (spdlog's source_loc is a non-owning const char*, unsafe with async sinks).
It lives in logging/internal/, is gated by #ifdef ICEBERG_HAS_SPDLOG, and is
NOT installed -- consumers obtain it via the default logger or the registry,
never by including spdlog headers.
- New ICEBERG_SPDLOG CMake option (default ON). config.h is ALWAYS generated
(only ICEBERG_HAS_SPDLOG's definedness varies) so logger.cc compiles in both
configurations; MakeDefaultLogger() prefers SpdLogger when compiled in, else
CerrLogger.
- Critically, ICEBERG_SPDLOG=OFF now UNWIRES the previously-unconditional spdlog
link (interface-lib lists + resolve_spdlog_dependency), not just the new
source -- so an OFF build has no spdlog dependency at all.
spdlog_logger_test (compiled only on the ON path) covers the level mapping
including fatal->critical and source-location forwarding.
Co-authored-by: Isaac
Final block: configuration-driven backend selection, mirroring MetricsReporters.
- Loggers::Register(type, factory) registers a named backend; Loggers::Load(props)
builds one, selecting the type from the "logger-impl" property key.
- Built-in factories: "noop", "cerr", and (only when built with ICEBERG_SPDLOG)
"spdlog". With no logger-impl set, the default is spdlog when compiled in, else
cerr -- logs by default, an intentional divergence from the metrics registry's
noop default.
- Loggers::LoadAndSetDefault(props) loads a logger and installs it as the process
default.
This completes the system end to end: levels -> Logger interface + default logger
-> CerrLogger/SpdLogger backends -> macros -> configuration-driven selection.
loggers_test covers load default/noop/cerr, unknown-type errors, empty-factory
rejection, custom Register, and LoadAndSetDefault.
Adds logging_end_to_end_test, which drives the public surface as an application
does -- now that every layer is present: configure a backend via the registry,
install it as the default, log through the LOG_* macros, and observe real output.
Covers registry -> default-slot -> macro -> backend -> std::cerr output, level
filtering through the full macro path, the compiled-backend identity of the
default (spdlog when ON, cerr when OFF), the "spdlog" factory by name, and a macro
statement reaching a real spdlog sink.
Co-authored-by: Isaac
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@kamcheungting-db@manuzhang