Skip to content

FIX(config) Respect log_level from settings.yaml and suppress premature debug output#9

Merged
zkraus merged 8 commits intomainfrom
zkraus/issue6
Apr 17, 2026
Merged

FIX(config) Respect log_level from settings.yaml and suppress premature debug output#9
zkraus merged 8 commits intomainfrom
zkraus/issue6

Conversation

@zkraus
Copy link
Copy Markdown
Contributor

@zkraus zkraus commented Apr 10, 2026

Settings.yaml log_level was ignored because config was loaded after --log-level argument default was set. Additionally, debug messages from config loading appeared before the logger was properly configured.

Changes:

  • Load config defaults before creating argparse arguments
  • Use config file log_level as default instead of hardcoded "INFO"
  • Remove loguru default handler before parsing args to suppress early debug output
  • Add log_config_status() to log config info AFTER logger is configured
  • Remove redundant --log-level from trigger/summary subcommands
  • Note: --log-level must now come BEFORE subcommand (e.g., rptool --log-level DEBUG write)

Fixes: #6

Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com

Signed-off-by: Zdenek Kraus zkraus@redhat.com

Summary by CodeRabbit

  • Bug Fixes

    • Log-level option is now global (can be given before the subcommand) and consistently applies across subcommands.
    • Invalid log-level values in configuration now raise errors instead of silently falling back.
  • Behaviour Changes

    • Startup logging honours the resolved log level earlier during launch.
    • Configuration discovery messages are less verbose; config-load failures are reported as errors.
  • Tests

    • Unit tests expanded to cover log-level precedence, validation, config-load errors and logging behaviour.

…re debug output

Settings.yaml log_level was ignored because config was loaded after --log-level
argument default was set. Additionally, debug messages from config loading appeared
before the logger was properly configured.

Changes:
- Load config defaults before creating argparse arguments
- Use config file log_level as default instead of hardcoded "INFO"
- Remove loguru default handler before parsing args to suppress early debug output
- Add log_config_status() to log config info AFTER logger is configured
- Remove redundant --log-level from trigger/summary subcommands
- Note: --log-level must now come BEFORE subcommand (e.g., rptool --log-level DEBUG write)

Fixes: #6

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Signed-off-by: Zdenek Kraus <zkraus@redhat.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 10, 2026

📝 Walkthrough

Walkthrough

Top-level CLI --log-level is now set from validated configuration defaults in create_main_parser(); duplicate subcommand --log-level options removed. Config loading raises on YAML/read errors. Dispatcher reorders Loguru/stderr handler setup and catches config validation errors to exit with code 1. Tests updated accordingly.

Changes

Cohort / File(s) Summary
CLI argument parsing
src/reportportal/ap.py
Moved --log-level to the top-level parser and set its default from _get_config_defaults(); validated log_level (uppercased, must be one of DEBUG, INFO, WARNING, ERROR); removed per-subcommand --log-level flags.
Configuration loading / defaults
src/reportportal/config.py
load_config_file() now logs differently (less path detail) and raises ValueError on YAML/read errors instead of returning {}; minor logging formatting change in get_effective_defaults() while preserving REQUESTS_CA_BUNDLE injection.
Dispatcher start-up & logging
src/reportportal/rp_dispatcher.py
Removes Loguru default handler at entry, installs a temporary stderr handler at a derived level, wraps create_main_parser() in try/except to catch ValueError and return exit code 1 on invalid config, then reconfigures handlers using the parsed args.log_level.
Unit tests
tests/unit/test_ap.py, tests/unit/test_config.py, tests/unit/test_rp_dispatcher_write.py, tests/unit/test_rp_dispatcher_write.py
Updated tests to supply --log-level before subcommands, added TestLogLevelConfig to cover config vs CLI precedence and invalid config values raising ValueError, adjusted tests to expect exceptions from invalid YAML, and patched config loading in integration tests to return {}.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as "User / CLI"
    participant Dispatcher as "rp_dispatcher"
    participant Parser as "ap.create_main_parser"
    participant Config as "config.load_config_file"
    participant Log as "Loguru / stderr handler"

    CLI->>Dispatcher: invoke command
    Dispatcher->>Log: remove default handler
    Dispatcher->>Log: add temporary stderr handler (level from env/config)
    Dispatcher->>Parser: call create_main_parser()
    Parser->>Config: _get_config_defaults() / load_config_file()
    Config-->>Parser: return defaults (or raise ValueError)
    alt config valid
        Parser-->>Dispatcher: return parser
        Dispatcher->>CLI: parse args
        Dispatcher->>Log: remove temp handlers
        Dispatcher->>Log: add stderr handler (level=args.log_level)
        Dispatcher->>Dispatcher: run command
    else config invalid
        Parser-->>Dispatcher: raises ValueError
        Dispatcher->>Log: log error
        Dispatcher-->>CLI: exit code 1
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I nosed the config, found the hidden tone,
Lifted flags to top-level, no more duplicate groan.
When YAML stumbles, I shout it loud and clear,
Handlers leap, stderr listens — logs now hear.
A hop, a tidy fix, the orchard’s calm and near.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: respecting log_level from settings.yaml and suppressing premature debug output through config-first loading.
Linked Issues check ✅ Passed The PR successfully implements the core requirement from issue #6: log_level from settings.yaml is now respected as the argparse default, and premature debug output is suppressed.
Out of Scope Changes check ✅ Passed All changes are directly related to the linked issue objectives: config loading sequencing, log level defaults, handler management, and test updates for the new behaviour.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch zkraus/issue6

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/reportportal/ap.py`:
- Around line 65-69: Normalize and validate the configured log level before
using it as the argparse default: ensure defaults["log_level"] (and any
LOG_LEVEL env/config value) is converted to upper() and checked against the
allowed choices ["DEBUG","INFO","WARNING","ERROR"], falling back to "INFO" if
invalid, then pass that validated value into parser.add_argument default; also
ensure the value passed to logger.add(level=...) is the validated, uppercased
string to avoid Loguru ValueError.

In `@tests/unit/test_ap.py`:
- Around line 611-672: Wrap the calls to reportportal.rp_dispatcher.main(...) in
a try/finally inside both test_no_premature_debug_messages_during_config_load
and test_config_status_logged_with_debug_level so that the Loguru global logger
is cleaned up after each test; in the finally block import logger from loguru
and call logger.remove() (and any other per-test restoration if you added sinks)
to ensure the global logger state added by main() is cleared and does not leak
into subsequent tests.

In `@tests/unit/test_config.py`:
- Around line 295-348: Both tests
(TestLogConfigStatus.test_log_config_status_file_not_found and
TestLogConfigStatus.test_log_config_status_empty_file) mutate the global Loguru
logger via logger.remove() and logger.add(...); update each test to save and
restore the original logger state around the assertions (use try/finally).
Specifically, before calling logger.remove(), capture the current handlers/state
(so you can restore it), then run the test logic that calls log_config_status(),
and in the finally block restore the original Loguru configuration (re-add the
saved handlers or reset to the saved state) so other tests are not affected.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 22105c1d-7f52-4742-aa8a-5f2fb714c3b6

📥 Commits

Reviewing files that changed from the base of the PR and between 1c7793c and 439a32a.

📒 Files selected for processing (5)
  • src/reportportal/ap.py
  • src/reportportal/config.py
  • src/reportportal/rp_dispatcher.py
  • tests/unit/test_ap.py
  • tests/unit/test_config.py

Comment thread src/reportportal/ap.py
Comment thread tests/unit/test_ap.py Outdated
Comment thread tests/unit/test_config.py Outdated
@zkraus zkraus requested a review from silvi-t April 13, 2026 10:41
Comment thread src/reportportal/config.py Outdated
Comment thread tests/unit/test_ap.py Outdated
Comment thread tests/unit/test_config.py Outdated
zkraus added 3 commits April 16, 2026 15:51
…premature debug output

Signed-off-by: Zdenek Kraus <zkraus@redhat.com>
…ppress premature debug output

Signed-off-by: Zdenek Kraus <zkraus@redhat.com>
… and suppress premature debug output

Signed-off-by: Zdenek Kraus <zkraus@redhat.com>
@zkraus
Copy link
Copy Markdown
Contributor Author

zkraus commented Apr 16, 2026

@coderabbitai please review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

@zkraus Sure, I'll review the changes right away!

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@zkraus zkraus requested a review from silvi-t April 16, 2026 14:06
Comment thread src/reportportal/config.py
Comment thread src/reportportal/config.py Outdated
…gs.yaml and suppress premature debug output

Signed-off-by: Zdenek Kraus <zkraus@redhat.com>
@zkraus
Copy link
Copy Markdown
Contributor Author

zkraus commented Apr 17, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/reportportal/ap.py (1)

65-76: Log-level validation looks good; minor UX note on failure mode.

The uppercase normalisation plus membership check correctly prevents invalid values from settings.yaml/LOG_LEVEL reaching logger.add(level=...). One small caveat: because this runs unconditionally inside create_main_parser(), an invalid log_level in the config will also break rptool --help / rptool --version, not just real invocations. If that matters, consider deferring validation until after parse_args (or falling back to INFO with a logger.warning) rather than raising. Otherwise LGTM — the dispatcher's ValueError handler makes this acceptable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/reportportal/ap.py` around lines 65 - 76, The current unconditional
validation of defaults.get("log_level") in create_main_parser() (checking
configured_log_level against valid_log_levels) causes an exception during simple
invocations like rptool --help or --version; instead defer or soften validation:
remove the hard raise in create_main_parser(), keep configured_log_level but if
it's invalid set parser's default to "INFO" and emit a runtime warning (via
logger.warning) after args are parsed in the main dispatcher, or alternatively
validate configured_log_level after parse_args and raise/handle there; update
references to configured_log_level, valid_log_levels, and parser.add_argument to
implement the deferred validation/fallback approach so help/version remain
usable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/reportportal/config.py`:
- Around line 57-60: The except block currently logs with Loguru formatting but
raises ValueError using unused `{}` placeholders and loses the original
traceback; update the except around reading the config to catch only concrete
errors (e.g., OSError and yaml.YAMLError), raise a ValueError with a properly
formatted message (using f-string or .format to inject config_file and e) and
chain the original exception with `from e`; reference the logger and config_file
variables and the ValueError raised in the except block so the change is applied
to that handler.

---

Nitpick comments:
In `@src/reportportal/ap.py`:
- Around line 65-76: The current unconditional validation of
defaults.get("log_level") in create_main_parser() (checking configured_log_level
against valid_log_levels) causes an exception during simple invocations like
rptool --help or --version; instead defer or soften validation: remove the hard
raise in create_main_parser(), keep configured_log_level but if it's invalid set
parser's default to "INFO" and emit a runtime warning (via logger.warning) after
args are parsed in the main dispatcher, or alternatively validate
configured_log_level after parse_args and raise/handle there; update references
to configured_log_level, valid_log_levels, and parser.add_argument to implement
the deferred validation/fallback approach so help/version remain usable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cc667a06-3a04-443a-aac8-d2bf5c000805

📥 Commits

Reviewing files that changed from the base of the PR and between 439a32a and f6d75af.

📒 Files selected for processing (5)
  • src/reportportal/ap.py
  • src/reportportal/config.py
  • src/reportportal/rp_dispatcher.py
  • tests/unit/test_ap.py
  • tests/unit/test_config.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/reportportal/rp_dispatcher.py
  • tests/unit/test_ap.py
  • tests/unit/test_config.py

Comment thread src/reportportal/config.py Outdated
zkraus added 2 commits April 17, 2026 13:28
… settings.yaml and suppress premature debug output

Signed-off-by: Zdenek Kraus <zkraus@redhat.com>
…el from settings.yaml and suppress premature debug output

Signed-off-by: Zdenek Kraus <zkraus@redhat.com>
@zkraus
Copy link
Copy Markdown
Contributor Author

zkraus commented Apr 17, 2026

Changes:

  • on config error, ValueError is raised. logging is handled by the caller to prevent double logging
  • few tests were improperly isolated, and were failing when real config file was containing an error -> mocked
  • removed leftovers of log_config_status()
  • initial logging is set to warning unless there is env varible LOG_LEVEL used by loguru on import, so user can override initial settings to debug config problems

@zkraus zkraus requested a review from silvi-t April 17, 2026 11:39
Comment thread src/reportportal/rp_dispatcher.py Outdated
Comment thread src/reportportal/config.py Outdated
Comment thread src/reportportal/config.py
…log_level from settings.yaml and suppress premature debug output

Signed-off-by: Zdenek Kraus <zkraus@redhat.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src/reportportal/config.py (1)

60-62: ⚠️ Potential issue | 🟡 Minor

Chain the raised ValueError and narrow the except.

Same findings as the prior round: raise ValueError(...) inside an except should use from e (Ruff B904) to preserve the original traceback, and the blind except Exception (Ruff BLE001) should be narrowed to the concrete errors actually thrown by open()/yaml.safe_load().

🛠️ Proposed fix
-    except Exception as e:
-        # need to raise ValueError to indicate critical problem
-        raise ValueError(f"Error reading config file {config_file} {e}")
+    except (OSError, yaml.YAMLError) as e:
+        # need to raise ValueError to indicate critical problem
+        raise ValueError(f"Error reading config file {config_file}: {e}") from e
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/reportportal/config.py` around lines 60 - 62, The except block catching
Exception when reading the config file should be narrowed to the specific errors
thrown by open() and yaml.safe_load() (e.g., FileNotFoundError, PermissionError,
OSError, and yaml.YAMLError) instead of a blind except, and when re-raising wrap
the new ValueError with the original exception using "from e" so the traceback
is preserved; update the handler around the code that uses open(config_file,
...) and yaml.safe_load(...) to catch those concrete exceptions and change
"raise ValueError(f'Error reading config file {config_file} {e}')" to raise
ValueError(...) from e.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/reportportal/config.py`:
- Around line 60-62: The except block catching Exception when reading the config
file should be narrowed to the specific errors thrown by open() and
yaml.safe_load() (e.g., FileNotFoundError, PermissionError, OSError, and
yaml.YAMLError) instead of a blind except, and when re-raising wrap the new
ValueError with the original exception using "from e" so the traceback is
preserved; update the handler around the code that uses open(config_file, ...)
and yaml.safe_load(...) to catch those concrete exceptions and change "raise
ValueError(f'Error reading config file {config_file} {e}')" to raise
ValueError(...) from e.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2b249e02-1362-45db-8dab-855f8b5c1fe8

📥 Commits

Reviewing files that changed from the base of the PR and between f6d75af and 9d39636.

📒 Files selected for processing (3)
  • src/reportportal/config.py
  • src/reportportal/rp_dispatcher.py
  • tests/unit/test_rp_dispatcher_write.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/reportportal/rp_dispatcher.py

@zkraus zkraus requested a review from silvi-t April 17, 2026 13:00
Copy link
Copy Markdown
Contributor

@silvi-t silvi-t left a comment

Choose a reason for hiding this comment

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

LGTM

@zkraus zkraus merged commit 5b45a98 into main Apr 17, 2026
4 checks passed
@silvi-t silvi-t deleted the zkraus/issue6 branch April 28, 2026 10:27
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.

settings: log_level value is ignored

2 participants