Add scenario names to log messages for improved debugging#4478
Merged
cidrblock merged 3 commits intoansible:mainfrom Jul 23, 2025
Merged
Add scenario names to log messages for improved debugging#4478cidrblock merged 3 commits intoansible:mainfrom
cidrblock merged 3 commits intoansible:mainfrom
Conversation
**User Story** As a molecule user, I want to see the name of the current scenario in molecule-generated log messages so I can better track progress and debug issues in multi-scenario runs. **Problem** - Log messages lacked scenario context, making debugging difficult - Heavy dependency on Rich's RichHandler for logging - enrich.Console's redirect=True behavior captured all stdout/stderr, breaking integration tests that expected specific stream separation - Duplicate utility functions (to_bool, should_do_markup) across modules **Solution** 1. **Scenario-aware logging**: Introduced ScenarioLoggerAdapter that injects scenario names into log records without string manipulation 2. **Custom logging handler**: Replaced RichHandler with MoleculeConsoleHandler that: - Bypasses Rich redirection by writing to original stderr - Preserves colored output using custom ANSI processing - Maintains proper stdout/stderr separation for testing 3. **Centralized ANSI processing**: Created AnsiOutput class with: - Rich-style markup processing ([red], [bold], etc.) - ANSI color constants and level-specific formatting - Environment-aware markup enabling/disabling 4. **Stream preservation**: Captured sys.stdout/stderr before enrich.Console initialization to enable direct writing **Key Changes** - src/molecule/logger.py: New MoleculeConsoleHandler + ScenarioLoggerAdapter - src/molecule/ansi_output.py: Centralized ANSI/markup processing - src/molecule/console.py: Captured original streams, moved utilities - All command modules: Updated to use get_scenario_logger() - Integration tests: Now pass with proper stderr routing **Technical Details** - enrich.Console redirect=True intercepts all sys.stdout/stderr writes - Solution captures original streams before Console initialization - MoleculeConsoleHandler writes directly to original_stderr - Preserves Rich markup support via custom ANSI conversion - ScenarioLoggerAdapter passes scenario via record.molecule_scenario **Testing** - Added comprehensive test suite for AnsiOutput (39 test cases) - Updated logger tests for new components - All integration tests pass with proper stream separation - Pre-commit hooks pass (ruff, mypy, pylint, etc.) **Compatibility** - No changes to user-visible output or behavior - Maintains all existing color/markup functionality - Preserves stdout/stderr routing for downstream tools
0ce95c0 to
3d56727
Compare
- Fix UnboundLocalError in api.py verifiers() function by using plugin_class.__name__ instead of pm.get_name(plugin) - Fix None config handling in ansible and testinfra verifiers - Update test_scenario_execute to use caplog fixture instead of patched_logger_info mock - Replace test_cache_path with tmp_path fixture for proper temporary directory handling - Mock run_command to create directory structure without executing ansible Both originally failing tests now pass: - tests/unit/test_api.py::test_api_verifiers - tests/unit/command/init/test_scenario.py::test_scenario_execute
Fix mypy and ruff type annotation errors for mock_run_command function.
alisonlhart
approved these changes
Jul 23, 2025
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.
User Story
As a Molecule user, I want to see the name of the current scenario in play in the Molecule-generated log messages so I can easily distinguish which scenario is generating specific log output when running multiple scenarios or debugging complex workflows.
Problem Statement
Molecule's current logging implementation mixes orchestration messages with Ansible output, making it difficult to trace which scenario is responsible for specific log entries. This is particularly problematic when:
Solution Overview
This PR implements scenario-aware logging by:
LoggerAdapterpatternTechnical Changes
Core Implementation
ScenarioLoggerAdapter: Extendslogging.LoggerAdapterto inject scenario names into log records viaextraattributesMoleculeConsoleHandler: Custom handler that formats log messages with scenario context and ANSI colorsstdout/stderrbeforeenrich.Consoleredirection to ensure proper test captureKey Files Modified
src/molecule/logger.pyScenarioLoggerAdapterclass for scenario context injectionMoleculeConsoleHandlerwith direct original stream accessget_scenario_logger()convenience functionsrc/molecule/console.pyoriginal_stdoutandoriginal_stderrbefore Console object initializationMultiple command/provisioner/verifier classes
__init__methods to uselogger.get_scenario_logger(__name__, scenario_name)Enrich Compatibility
The implementation specifically addresses
enrich.Console(redirect=True)behavior:Output Examples
Before
After
Testing
Breaking Changes
None. The changes are additive and maintain full backward compatibility.
Performance Impact
Minimal. The LoggerAdapter pattern adds negligible overhead, and direct stream access is more efficient than the previous redirect manipulation approach.