Skip to content

Conversation

@mcastrol
Copy link

This change adds dynamic logger discovery that automatically configures logging for all modules in the template_agent package hierarchy.

What this fixes:

  • Previous implementation required manual updates to logger list when adding new modules
  • New modules wouldn't get proper logging configuration automatically
  • Required developers to remember to update get_uvicorn_log_config()

What this adds:

  • _discover_app_loggers() function that dynamically walks the package tree
  • Automatic discovery of all submodules and subpackages
  • Caching mechanism to avoid repeated package traversal
  • Graceful fallback to common patterns if package import fails

Benefits:

  • Zero maintenance - new modules automatically get logging configured
  • Better developer experience - no manual logging setup needed
  • Consistent logging behavior across all modules
  • Performance optimized with result caching

Testing:

  • All 39 existing tests pass
  • Ruff linting passes
  • Backwards compatible - no breaking changes

This improvement was successfully implemented and tested in the harbor-agent fork where it has been running in production.

This change adds dynamic logger discovery that automatically configures
logging for all modules in the template_agent package hierarchy.

**What this fixes:**
- Previous implementation required manual updates to logger list when adding new modules
- New modules wouldn't get proper logging configuration automatically
- Required developers to remember to update get_uvicorn_log_config()

**What this adds:**
- _discover_app_loggers() function that dynamically walks the package tree
- Automatic discovery of all submodules and subpackages
- Caching mechanism to avoid repeated package traversal
- Graceful fallback to common patterns if package import fails

**Benefits:**
- Zero maintenance - new modules automatically get logging configured
- Better developer experience - no manual logging setup needed
- Consistent logging behavior across all modules
- Performance optimized with result caching

**Testing:**
- All 39 existing tests pass
- Ruff linting passes
- Backwards compatible - no breaking changes

This improvement was successfully implemented and tested in the
harbor-agent fork where it has been running in production.
webbnh

This comment was marked as resolved.

@tuhinsharma121
Copy link
Contributor

@mcastrol Thanks for creating the PR. Can you please address @webbnh's comments?

Improvements based on PR review by @webbnh:

1. Use underscore for unused variables in pkgutil.walk_packages()
   - Changed 'for importer, modname, ispkg' to 'for _, modname, _'
   - More Pythonic to explicitly mark unused variables

2. Verify fallback paths exist before adding to logger list
   - Added try/except ImportError for each fallback pattern
   - Only adds logger names for modules that can actually be imported
   - Prevents logging configuration for non-existent modules

3. Minimize exception handling scope
   - Removed AttributeError from exception tuple (impossible due to hasattr guard)
   - Minimized try block to only cover importlib.import_module(package_name)
   - Moved package.__path__ check and pkgutil.walk_packages outside try block
   - Improves code clarity and prevents unintended exception masking
@mcastrol
Copy link
Author

@webbnh thanks for the feedback. Check all three comments in last commit.

Copy link

@webbnh webbnh left a comment

Choose a reason for hiding this comment

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

The changes look good, but I'm wondering if there's a gap.

@webbnh

This comment was marked as resolved.

@codecov-commenter
Copy link

codecov-commenter commented Oct 30, 2025

Codecov Report

❌ Patch coverage is 96.42857% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
template_agent/utils/pylogger.py 96.42% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@tuhinsharma121
Copy link
Contributor

@mcastrol the pre-commit is failing. it needs a fix (run pre-commit run --all-files). And also, please add a pytest for this new method.

@tuhinsharma121 tuhinsharma121 self-assigned this Oct 30, 2025
…ixes, and comprehensive tests

- Add Optional[List[str]] type annotation to _DISCOVERED_LOGGERS_CACHE to fix mypy unreachable code error
- Apply ruff formatting fixes (trailing comma, quote consistency, line formatting)
- Add comprehensive pytest test suite for _discover_app_loggers function with 6 test cases
- Tests cover real package discovery, caching, fallback patterns, and edge cases
- All 45 tests passing, pre-commit hooks satisfied
@mcastrol
Copy link
Author

@tuhinsharma121 done. please check.

webbnh

This comment was marked as resolved.

Implementation improvements:
- Use named field access (pkg.name) instead of tuple unpacking in walk_packages()
  This makes the code more explicit and maintainable by using ModuleInfo's field name

Test improvements:
- Move module import to top of file (pylogger_module)
  Eliminates redundant imports in each test method
- Remove cache reset from individual test methods
  setup_method() already handles this for all tests
- Change identity check to equality check for cached results
  Tests interface contract (equality) not implementation detail (identity)
- Add assertions for nonexistent patterns in fallback test
  Stronger assertion than just checking for no errors
- Use ModuleNotFoundError instead of generic ImportError in mocks
  Matches actual Python behavior more accurately
- Add "MOCK:" prefix to mock exception messages
  Makes it clear exceptions come from test mocks, not real code
- Use AssertionError for unexpected mock calls
  Causes test to fail obviously if mock is called incorrectly
- Fix mock function signatures to accept all parameters
  side_effect(name, package=None) matches importlib.import_module signature
- Use ModuleInfo objects in walk_packages mock
  Accurately represents actual return type from pkgutil
- Return generator instead of list from walk_packages mock
  Matches actual pkgutil.walk_packages() behavior
- Remove implementation detail assertion (mock_walk.assert_called_once)
  Tests functionality, not how it's achieved
- Simplify assertions where any() is not needed
  More readable and consistent with other tests

All changes follow best practices:
- Tests enforce interface contracts without restricting implementation
- Mocks accurately represent real function signatures and return types
- Stronger assertions provide better test coverage
- Code is more maintainable and conventional

Addresses all feedback from code review.
@mcastrol
Copy link
Author

mcastrol commented Nov 4, 2025

@webbnh check the changes.

Copy link

@webbnh webbnh left a comment

Choose a reason for hiding this comment

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

@mcastrol, it all looks good to me, now, with the possible exception of the comment that I made earlier. You haven't updated that part of the code, and you haven't responded to the comment.

@webbnh
Copy link

webbnh commented Nov 4, 2025

@tuhinsharma121, apparently this PR needs testing approval again.

Address PR feedback by refactoring _discover_app_loggers function to use
a single common exit point and eliminate duplicated cache-and-return code.

Changes:
- Use try-except-else pattern for clearer control flow
- Invert hasattr check to avoid early returns
- Single exit point at end of function handles caching for all paths
- Eliminates three instances of duplicated code

This makes the code more maintainable and prevents future bugs from
inconsistent updates across multiple exit points.
webbnh

This comment was marked as resolved.

Sign up for free to 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.

4 participants