feat(interfaces): implement GlobalLoggerRegistry for runtime binding (#174)#181
Merged
Conversation
This commit introduces the GlobalLoggerRegistry class to resolve the circular dependency between thread_system and logger_system. The registry provides a centralized, thread-safe mechanism for managing logger instances across all subsystems. Key features implemented: - Thread-safe singleton pattern using Meyer's singleton idiom - std::shared_mutex for efficient read/write locking - Default and named logger management - Factory-based lazy initialization for deferred logger creation - NullLogger fallback for unregistered logger requests - Convenience functions (get_registry, get_logger) The NullLogger class provides a safe no-op implementation that: - Returns success for all logging operations - Always reports log level as 'off' - Ensures code functions silently when logging is not configured Public API: - register_logger(name, logger): Register a named logger - get_logger(name): Retrieve a named logger (returns NullLogger if not found) - unregister_logger(name): Remove a named logger - set_default_logger(logger): Set the default logger - get_default_logger(): Get the default logger (returns NullLogger if not set) - register_factory(name, factory): Register lazy initialization factory - set_default_factory(factory): Set factory for default logger - has_logger(name): Check if logger/factory exists - has_default_logger(): Check if default logger/factory exists - clear(): Remove all registered loggers and factories - size(): Get count of registered named loggers This implementation is part of Issue #174 and blocks Phase 2/3 work on the runtime binding migration. Refs: #174
This commit adds unit tests covering all aspects of the GlobalLoggerRegistry implementation, ensuring thread safety and correctness. Test categories implemented: 1. Singleton Tests: - Instance returns same reference - get_registry() convenience function works correctly 2. Default Logger Tests: - Returns NullLogger when no default is set - set_default_logger() succeeds with valid logger - set_default_logger() fails with null - Convenience function get_logger() returns default 3. Named Logger Tests: - register_logger() with valid parameters - Empty name validation - Null logger validation - Logger replacement behavior - get_logger() retrieval - NullLogger fallback for unregistered names - unregister_logger() behavior 4. Factory Tests: - Lazy initialization pattern - Factory called only once - Factory validation (empty name, null factory) - Factory vs existing logger precedence - register_logger() removes associated factory - Default factory lazy initialization 5. NullLogger Tests: - All operations succeed - Same instance returned - Always reports disabled 6. Clear and Size Tests: - clear() removes all state - size() returns correct count 7. Thread Safety Tests (35 test cases total): - Concurrent registration (10 threads, 100 loggers each) - Concurrent retrieval (10 threads, 1000 retrievals each) - Concurrent factory creation (race condition test) - Concurrent default logger access - Mixed read/write operations 8. Integration Tests: - Logging through registry - Multiple named loggers All tests pass with no race conditions or deadlocks detected. Refs: #174
This commit adds the logger-related headers to the main common.h aggregated header file for convenient access. Added includes: - interfaces/logger_interface.h: Core ILogger interface and log types - interfaces/global_logger_registry.h: GlobalLoggerRegistry singleton This allows users to access the logging infrastructure with a single include of <kcenon/common/common.h> instead of having to include individual header files. Refs: #174
This commit updates the documentation to include the new GlobalLoggerRegistry class and related components. Changes to API_REFERENCE.md: - Updated ILogger section with correct header path and complete interface - Added comprehensive GlobalLoggerRegistry documentation: - Singleton access pattern - Default logger management methods - Named logger management methods - Factory support for lazy initialization - Utility methods (clear, size, null_logger) - Convenience functions - Usage examples with code samples - Added NullLogger documentation Changes to CHANGELOG.md: - Added GlobalLoggerRegistry to [Unreleased] section - Listed key features: thread-safe singleton, named loggers, factory support - Referenced Issue #174 Refs: #174
kcenon
added a commit
that referenced
this pull request
Apr 13, 2026
…174) (#181) * feat(interfaces): implement GlobalLoggerRegistry for runtime binding This commit introduces the GlobalLoggerRegistry class to resolve the circular dependency between thread_system and logger_system. The registry provides a centralized, thread-safe mechanism for managing logger instances across all subsystems. Key features implemented: - Thread-safe singleton pattern using Meyer's singleton idiom - std::shared_mutex for efficient read/write locking - Default and named logger management - Factory-based lazy initialization for deferred logger creation - NullLogger fallback for unregistered logger requests - Convenience functions (get_registry, get_logger) The NullLogger class provides a safe no-op implementation that: - Returns success for all logging operations - Always reports log level as 'off' - Ensures code functions silently when logging is not configured Public API: - register_logger(name, logger): Register a named logger - get_logger(name): Retrieve a named logger (returns NullLogger if not found) - unregister_logger(name): Remove a named logger - set_default_logger(logger): Set the default logger - get_default_logger(): Get the default logger (returns NullLogger if not set) - register_factory(name, factory): Register lazy initialization factory - set_default_factory(factory): Set factory for default logger - has_logger(name): Check if logger/factory exists - has_default_logger(): Check if default logger/factory exists - clear(): Remove all registered loggers and factories - size(): Get count of registered named loggers This implementation is part of Issue #174 and blocks Phase 2/3 work on the runtime binding migration. Refs: #174 * test(interfaces): add comprehensive tests for GlobalLoggerRegistry This commit adds unit tests covering all aspects of the GlobalLoggerRegistry implementation, ensuring thread safety and correctness. Test categories implemented: 1. Singleton Tests: - Instance returns same reference - get_registry() convenience function works correctly 2. Default Logger Tests: - Returns NullLogger when no default is set - set_default_logger() succeeds with valid logger - set_default_logger() fails with null - Convenience function get_logger() returns default 3. Named Logger Tests: - register_logger() with valid parameters - Empty name validation - Null logger validation - Logger replacement behavior - get_logger() retrieval - NullLogger fallback for unregistered names - unregister_logger() behavior 4. Factory Tests: - Lazy initialization pattern - Factory called only once - Factory validation (empty name, null factory) - Factory vs existing logger precedence - register_logger() removes associated factory - Default factory lazy initialization 5. NullLogger Tests: - All operations succeed - Same instance returned - Always reports disabled 6. Clear and Size Tests: - clear() removes all state - size() returns correct count 7. Thread Safety Tests (35 test cases total): - Concurrent registration (10 threads, 100 loggers each) - Concurrent retrieval (10 threads, 1000 retrievals each) - Concurrent factory creation (race condition test) - Concurrent default logger access - Mixed read/write operations 8. Integration Tests: - Logging through registry - Multiple named loggers All tests pass with no race conditions or deadlocks detected. Refs: #174 * refactor(common): add logger interfaces to aggregated header This commit adds the logger-related headers to the main common.h aggregated header file for convenient access. Added includes: - interfaces/logger_interface.h: Core ILogger interface and log types - interfaces/global_logger_registry.h: GlobalLoggerRegistry singleton This allows users to access the logging infrastructure with a single include of <kcenon/common/common.h> instead of having to include individual header files. Refs: #174 * docs(interfaces): add GlobalLoggerRegistry API documentation This commit updates the documentation to include the new GlobalLoggerRegistry class and related components. Changes to API_REFERENCE.md: - Updated ILogger section with correct header path and complete interface - Added comprehensive GlobalLoggerRegistry documentation: - Singleton access pattern - Default logger management methods - Named logger management methods - Factory support for lazy initialization - Utility methods (clear, size, null_logger) - Convenience functions - Usage examples with code samples - Added NullLogger documentation Changes to CHANGELOG.md: - Added GlobalLoggerRegistry to [Unreleased] section - Listed key features: thread-safe singleton, named loggers, factory support - Referenced Issue #174 Refs: #174
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR implements
GlobalLoggerRegistry, a thread-safe singleton registry for managing logger instances across all subsystems. It resolves the circular dependency betweenthread_systemandlogger_systemby providing a centralized, decoupled logging registry that can be bound at runtime.Problem Statement
Currently, these systems have problematic interdependencies:
logger_systemdepends onthread_systemfor async operationsthread_systemdefines its ownlogger_interface.hto prevent circular importsThis creates maintenance and extensibility challenges.
Solution
GlobalLoggerRegistryprovides:Changes
New Files
include/kcenon/common/interfaces/global_logger_registry.h- Implementation of GlobalLoggerRegistry and NullLoggertests/global_logger_registry_test.cpp- Comprehensive unit tests (35 test cases)Modified Files
include/kcenon/common/common.h- Added logger interface includes to aggregated headertests/CMakeLists.txt- Added new test targetdocs/API_REFERENCE.md- Added GlobalLoggerRegistry documentationdocs/CHANGELOG.md- Added changelog entryAPI Overview
Test Coverage
35 test cases covering:
All tests pass with no race conditions or deadlocks detected.
Breaking Changes
None. This is a new feature addition.
Impact
This implementation is part of Issue #174 and blocks Phase 2/3 work on the runtime binding migration. Once merged, dependent issues (#175, #176) can proceed.
Closes #174