Skip to content

fix: logging refinements#3571

Merged
cademirch merged 19 commits intosnakemake:mainfrom
cademirch:logging-fixes
Sep 15, 2025
Merged

fix: logging refinements#3571
cademirch merged 19 commits intosnakemake:mainfrom
cademirch:logging-fixes

Conversation

@cademirch
Copy link
Copy Markdown
Contributor

@cademirch cademirch commented May 13, 2025

This PR refines some of the changes from the logging refactor to tackle some issues as well as simplify the code.

Changes:

ExecMode added to OutputSettings:

  • ExecMode is critical to setting up the logger and controls how logs are written, so from this perspective I think it makes sense that ExecMode fits here
  • Moving ExecMode here allows the logger to be setup in SnakemakeAPI, which has multiple positive effects: the logger only needs to be setup once in all of Snakemake's lifecycle, the logger is setup before the workflow, allowing for workflow files to use the logger (Logging broken yet again #3558), and the logger does not need to manage state anymore.
  • This could be seen as a breaking change, though I've set the default for this field to be ExecMode.DEFAULT so existing callers would be unaffected.

Setup logger no longer dependent on executor_plugin.common_settings.dryrun_exec

  • Another reason the logger had to be setup late in the Snakemake lifecycle was that the stdout setting was dependent on this executor plugin setting
  • During refactoring I didn't question this, but now after looking at most of the executor plugins, I haven't seen any that use this, so I'm not sure the rationale behind tying stdout to this. @johanneskoester do you happen to know?

QueueHandler only used for plugins

  • Only spin up queue overhead for logger plugins if they are being used.

Added more tests

  • Added test for specifiyng logger in Snakefile

QC

  • The PR contains a test case for the changes or the changes are already covered by an existing test case.
  • The documentation (docs/) is updated to reflect the changes or this is not necessary (e.g. if the change does neither modify the language nor the behavior or functionalities of Snakemake).

Summary by CodeRabbit

  • New Features

    • Added configurable output settings to control log level overrides, plugin handler usage, and file logging.
    • Added comprehensive logging tests and supporting test workflows to validate logging behavior and failure scenarios.
  • Bug Fixes

    • Centralized and stabilized logger initialization for more consistent logging across runs.
  • Refactor

    • Simplified logging setup by removing mode-based branching and consolidating output-settings creation and handler management.
  • Documentation

    • Documented the logging module and centralized logger management.
  • Chores

    • Removed an outdated logfile test and updated test coverage.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2025

📝 Walkthrough

Walkthrough

Logger initialization and configuration are centralized: SnakemakeApi now sets up logging at construction and when a workflow starts; LoggerManager and handlers were simplified (removed mode-based branching); OutputSettings gained logging-related fields; CLI creation of OutputSettings was extracted; comprehensive logging tests and test Snakefiles were added; an obsolete test was removed.

Changes

Cohort / File(s) Change Summary
API / logger entrypoints
src/snakemake/api.py
Added SnakemakeApi.__post_init__ to call setup_logger() at construction; workflow now calls logger_manager.setup_logfile(workdir=...); setup_logger(self) signature simplified (removed stdout, mode, dryrun) and scattered setup calls removed.
Logging core
src/snakemake/logging.py
Removed mode-based branching and initialized/mode state; LoggerManager.setup now takes (handlers, settings); setup_logfile accepts optional workdir, creates log dir immediately, stores handler→path mapping; simplified handler/plugin/stream logic and DefaultFilter changes.
Settings
src/snakemake/settings/types.py
Extended OutputSettings with log_level_override: Optional[int] = None, skip_plugin_handlers: bool = False, and enable_file_logging: bool = True.
CLI / output settings factory
src/snakemake/cli.py
New function create_output_settings(args, log_handler_settings) -> OutputSettings and replaced inline OutputSettings construction with this factory; added imports for logging and SourceFileLoader.
Workflow logging condition
src/snakemake/workflow.py
Removed dependency on logger initialization flag when deciding to log rulegraph; now uses logger_manager.needs_rulegraph only.
Tests (removed)
tests/tests.py
Removed old test_logfile() function.
Tests (added)
tests/test_logging.py
Added comprehensive logging tests: logfile presence, custom logging config, in-workflow logger, dryrun/full log events, and rule-failure logging tests.
Test Snakefiles
tests/logging/test_logging_config/Snakefile
tests/logging/test_rule_failure/Snakefile
tests/logging/test_workflow_logger/Snakefile
Added Snakefiles to exercise custom logging config, a failing rule, and workflow logger integration.
Test artifacts
tests/logging/test_logging_config/results/0.txt
.../1.txt
.../2.txt
.../3.txt
.../4.txt
Added small result files used by logging tests (single-line contents).
Docs
docs/project_info/codebase.rst
Added documentation entry describing the logging module and LoggerManager.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant SnakemakeApi
    participant LoggerManager
    participant WorkflowApi

    User->>CLI: supply args
    CLI->>SnakemakeApi: instantiate with OutputSettings (via create_output_settings)
    SnakemakeApi->>SnakemakeApi: __post_init__ -> setup_logger()
    SnakemakeApi->>LoggerManager: setup(handlers, settings)
    User->>SnakemakeApi: start workflow(workdir)
    SnakemakeApi->>LoggerManager: setup_logfile(workdir)
    SnakemakeApi->>WorkflowApi: instantiate WorkflowApi (logging already configured)
    WorkflowApi->>LoggerManager: emit events/logs (handled by configured handlers)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • johanneskoester
  • fgvieira

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ❓ Inconclusive The PR description provides useful rationale and a QC checklist, but it contains an evident inconsistency with the file-level summary: the code summaries show new OutputSettings fields (log_level_override, skip_plugin_handlers, enable_file_logging) and changes to logger initialization, while the PR text states that ExecMode was added to OutputSettings; additionally the QC checkboxes remain unchecked, so the description is not fully reliable for reviewers as-is. Please update the PR description to accurately reflect the actual code changes (clarify whether ExecMode was added or replaced and explicitly list the new OutputSettings fields), mark and complete the QC checklist (which tests and docs are included or pending), and call out any remaining planned work or breaking-change considerations so reviewers can verify completeness.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title "fix: logging refinements" is concise and directly related to the primary changes in the changeset (centralizing and simplifying logging behavior), so it clearly communicates the main intent to reviewers scanning history.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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
Contributor

@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: 2

🧹 Nitpick comments (7)
src/snakemake/logging.py (4)

408-413: Use a single-line boolean return for the new filter rule

The added guard works, but you can collapse the last two lines into one boolean expression (ruff SIM103).
Keeps the method crisp and avoids an additional branch.

-        if event == LogEvent.WORKFLOW_STARTED:
-            return False
-
-        return True
+        return event != LogEvent.WORKFLOW_STARTED
🧰 Tools
🪛 Ruff (0.8.2)

410-413: Return the condition not event == LogEvent.WORKFLOW_STARTED directly

Replace with return not event == LogEvent.WORKFLOW_STARTED

(SIM103)


565-572: Inconsistent log level for the default stream handler in REMOTE mode

ExecMode.SUBPROCESS limits the default handler to ERROR, but ExecMode.REMOTE installs the same handler without level restriction.
If REMOTE workers are noisy this will flood the parent process.
Consider aligning the behaviour:

-        elif self.mode == ExecMode.REMOTE:
-            self.logger.addHandler(self._default_streamhandler())
+        elif self.mode == ExecMode.REMOTE:
+            handler = self._default_streamhandler()
+            handler.setLevel(logging.ERROR)   # mirror SUBPROCESS default
+            self.logger.addHandler(handler)

588-601: Minor: store the queue on the listener instead of the manager

self._queue is created only for wiring the QueueListener.
Unless the queue is accessed elsewhere, keeping it as a private attribute of the listener avoids an extra attribute on the manager:

-            self._queue = Queue(-1)
-            self.queue_listener = logging.handlers.QueueListener(
-                self._queue,
+            _queue = Queue(-1)
+            self.queue_listener = logging.handlers.QueueListener(
+                _queue,
                 *other_handlers,
                 respect_handler_level=True,
             )
             self.queue_listener.start()
-            self.logger.addHandler(logging.handlers.QueueHandler(self._queue))
+            self.logger.addHandler(logging.handlers.QueueHandler(_queue))

665-684: Path handling in setup_logfile can be simplified & made pathlib-safe

  1. os.path.join on a Path object may raise on some platforms.
  2. utils.makedirs() already exists for this purpose.
  3. Mixing string & Path hurts readability.
-from snakemake.utils import makedirs
-...
-            if workdir:
-                logdir = os.path.join(workdir, ".snakemake", "log")
-            else:
-                logdir = os.path.join(".snakemake", "log")
-            try:
-                os.makedirs(logdir, exist_ok=True)
-                logfile = os.path.abspath(
-                    os.path.join(
-                        logdir,
-                        datetime.datetime.now().isoformat().replace(":", "")
-                        + ".snakemake.log",
-                    )
-                )
+            from pathlib import Path
+            logdir_path = (
+                Path(workdir) if workdir is not None else Path(".")
+            ) / ".snakemake" / "log"
+            try:
+                logdir_path.mkdir(parents=True, exist_ok=True)
+                logfile = (
+                    logdir_path
+                    / f"{datetime.datetime.now().isoformat().replace(':','')}.snakemake.log"
+                )
                 handler = self._default_filehandler(logfile)
                 self.logger.addHandler(handler)
                 self.logfile_handlers[handler] = str(logfile)
src/snakemake/settings/types.py (1)

398-406: OutputSettings.mode duplicates WorkflowSettings.exec_mode

Both dataclasses now carry an execution-mode field (WorkflowSettings.exec_mode and OutputSettings.mode).
Having two sources of truth risks divergence, e.g. if one is mutated without updating the other.

Consider:

  1. Removing one of the fields, or
  2. Making one a @property view of the other, or
  3. Adding a validation check in __post_init__ to assert they match.

This will prevent subtle bugs where the wrong instance is consulted.

tests/tests.py (2)

48-52: More helpful failure diagnostics for multi-file scenarios

You already improved the error message with the directory path (👍).
Consider also logging the contents of glob.glob(...) when the list is empty – this makes triaging CI failures quicker (e.g. mis-configured work-dir vs. wrong filename pattern).

-    assert log_files, "No log files found"
+    assert log_files, f"No log files found in {log_dir}. Contents: {os.listdir(log_dir)}"

67-90: New test looks solid but can be tightened & sped up

  1. The stmts list is static; iterate once instead of sorting files every time.
  2. glob.glob + sort + [0] can be replaced with max(..., key=os.path.getmtime) which avoids a Python-level sort of the whole list.
-    log_files = glob.glob(os.path.join(log_dir, "*.snakemake.log"))
-    assert log_files, "No log files found"
-
-    log_files.sort(key=os.path.getmtime, reverse=True)
-    latest_log = log_files[0]
+    log_files = glob.glob(os.path.join(log_dir, "*.snakemake.log"))
+    assert log_files, f"No log files found in {log_dir}"
+
+    latest_log = max(log_files, key=os.path.getmtime)

These micro-changes make the test fractionally faster and the intent a bit clearer.
Everything else—including cleanup—looks correct.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67ad5eb and 13cfda4.

📒 Files selected for processing (7)
  • src/snakemake/api.py (4 hunks)
  • src/snakemake/cli.py (1 hunks)
  • src/snakemake/logging.py (4 hunks)
  • src/snakemake/settings/types.py (1 hunks)
  • src/snakemake/workflow.py (1 hunks)
  • tests/test_workflow_logger/Snakefile (1 hunks)
  • tests/tests.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.py`: Do not try to improve formatting. Do not suggest type annotations for functions that are defined inside of functions or methods. Do not suggest type annotation of the `s...

**/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

  • src/snakemake/settings/types.py
  • tests/tests.py
  • src/snakemake/cli.py
  • src/snakemake/logging.py
  • src/snakemake/api.py
  • src/snakemake/workflow.py
🧬 Code Graph Analysis (2)
src/snakemake/logging.py (2)
src/snakemake/workflow.py (2)
  • workdir (1646-1650)
  • dryrun (393-397)
src/snakemake/utils.py (1)
  • makedirs (293-300)
src/snakemake/api.py (1)
src/snakemake/logging.py (2)
  • setup_logfile (665-687)
  • setup (552-602)
🪛 Ruff (0.8.2)
src/snakemake/logging.py

410-413: Return the condition not event == LogEvent.WORKFLOW_STARTED directly

Replace with return not event == LogEvent.WORKFLOW_STARTED

(SIM103)

⏰ Context from checks skipped due to timeout of 90000ms (34)
  • GitHub Check: tests (10, windows-latest, py312)
  • GitHub Check: tests (10, ubuntu-latest, py312)
  • GitHub Check: tests (10, ubuntu-latest, py311)
  • GitHub Check: tests (9, windows-latest, py312)
  • GitHub Check: tests (9, ubuntu-latest, py312)
  • GitHub Check: tests (9, ubuntu-latest, py311)
  • GitHub Check: tests (8, windows-latest, py312)
  • GitHub Check: tests (8, ubuntu-latest, py312)
  • GitHub Check: tests (8, ubuntu-latest, py311)
  • GitHub Check: tests (7, windows-latest, py312)
  • GitHub Check: tests (7, ubuntu-latest, py312)
  • GitHub Check: tests (7, ubuntu-latest, py311)
  • GitHub Check: tests (6, windows-latest, py312)
  • GitHub Check: tests (6, ubuntu-latest, py312)
  • GitHub Check: tests (6, ubuntu-latest, py311)
  • GitHub Check: tests (5, windows-latest, py312)
  • GitHub Check: tests (5, ubuntu-latest, py312)
  • GitHub Check: tests (5, ubuntu-latest, py311)
  • GitHub Check: tests (4, macos-latest, py312)
  • GitHub Check: tests (4, windows-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py311)
  • GitHub Check: tests (3, macos-latest, py312)
  • GitHub Check: tests (3, windows-latest, py312)
  • GitHub Check: tests (3, ubuntu-latest, py312)
  • GitHub Check: tests (3, ubuntu-latest, py311)
  • GitHub Check: tests (2, macos-latest, py312)
  • GitHub Check: tests (2, windows-latest, py312)
  • GitHub Check: tests (2, ubuntu-latest, py312)
  • GitHub Check: tests (2, ubuntu-latest, py311)
  • GitHub Check: tests (1, macos-latest, py312)
  • GitHub Check: tests (1, windows-latest, py312)
  • GitHub Check: tests (1, ubuntu-latest, py312)
  • GitHub Check: tests (1, ubuntu-latest, py311)
🔇 Additional comments (6)
src/snakemake/workflow.py (1)

1163-1167: Confirm that logger_manager.setup() is always invoked before rulegraph logging

logger_manager.initialized was removed, so log_rulegraph() now relies solely on needs_rulegraph.
If a workflow reaches this point before LoggerManager.setup() runs, needs_rulegraph is still False and no rule-graph will be emitted, even if a plugin actually wants it.

Please double-check the execution order (especially for CLI entry-points) or guard the call with a fallback such as:

if getattr(logger_manager, "needs_rulegraph", False):
    ...
src/snakemake/cli.py (1)

1994-1994: Good addition of execution mode to output settings

Adding the execution mode from CLI arguments to the OutputSettings constructor aligns with centralizing logger setup in the SnakemakeAPI. This change enables proper logger initialization before workflow execution starts.

tests/test_workflow_logger/Snakefile (3)

1-3: Logger usage in workflow file looks good

Testing different logging severity levels (info, warning, error) is a good approach to verify the refined logging system.


5-8: Rule 'all' implementation is correct

The rule properly specifies the final targets using expand to generate multiple output files.


10-15: Rule 'a' implementation is correct

The rule correctly uses wildcards to generate the output files with their indices.

src/snakemake/api.py (1)

147-151: setup_logfile() should run after WorkdirHandler.change_to()

setup_logfile(workdir=workdir) executes before the WorkdirHandler actually chdirs into workdir.
If any relative paths are used inside setup_logfile (or outside callers forget to pass workdir), the log ends up in the calling dir, not the workflow dir.

Two low-impact fixes:

-        snakefile = resolve_snakefile(snakefile)
-        logger_manager.setup_logfile(workdir=workdir)
+        snakefile = resolve_snakefile(snakefile)
+
+        # order matters: change into workdir first, then open the logfile there
+        # (WorkdirHandler.change_to() is triggered inside WorkflowApi.__post_init__)
+

…or, move the setup_logfile() call into WorkflowApi.__post_init__() right after the directory change.

Comment thread src/snakemake/api.py
Comment thread src/snakemake/api.py
Comment thread src/snakemake/settings/types.py Outdated
keep_logger: bool = False
stdout: bool = False
benchmark_extended: bool = False
mode: ExecMode = ExecMode.DEFAULT
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So, what you do here is adding exec mode here but not removing it from WorkflowSettings?

If we would keep the old way, couldn't the logger behavior just be modified once the exec mode is known, instead of setting it up again there? This way, one would avoid the multiple logger setups as well.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Another alternative: what if we don't set the execMode here but instead offer settings for the individual logger behavior that so far is triggered by the exec mode. Then, whoever calls the API would have full control, and we don't have that duplication of settings. When the CLI calls the API, it could then set those settings according to exec mode (no need to expose them to command line flags). And their default could be the current ExecMode.DEFAULT behavior.

@johanneskoester
Copy link
Copy Markdown
Contributor

Regarding dryrun and stdout, the rationale was that when you do a dryrun, you want logging to happen on stdout so that you can easily pipe into less. But this can be handled differently as well, by just the cli setting a respective OutputSettings attribute if args.dryrun == True.

@cademirch
Copy link
Copy Markdown
Contributor Author

Thanks for the review @johanneskoester, will try to address this weekend.

Copy link
Copy Markdown
Contributor

@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: 0

🧹 Nitpick comments (2)
src/snakemake/logging.py (2)

414-415: Simplify the return statement as suggested by static analysis.

The filtering logic is correct, but it can be simplified for better readability.

Apply this diff to simplify the return statement:

-        if event == LogEvent.WORKFLOW_STARTED:
-            return False
+        if event == LogEvent.WORKFLOW_STARTED:
+            return False

Actually, you can make it even more concise:

-        if event == LogEvent.WORKFLOW_STARTED:
-            return False
-
-        return True
+        return event != LogEvent.WORKFLOW_STARTED

650-654: Apply static analysis suggestion for cleaner dictionary iteration.

The logic is correct, but the dictionary iteration can be improved as suggested by static analysis.

Apply this diff to improve the dictionary iteration:

-        if self.settings.enable_file_logging:
-            for handler in self.logfile_handlers.keys():
+        if self.settings.enable_file_logging:
+            for handler in self.logfile_handlers:
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b6ed2c and 85578b6.

📒 Files selected for processing (6)
  • src/snakemake/api.py (4 hunks)
  • src/snakemake/cli.py (2 hunks)
  • src/snakemake/logging.py (5 hunks)
  • src/snakemake/settings/types.py (1 hunks)
  • src/snakemake/workflow.py (1 hunks)
  • tests/tests.py (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/snakemake/settings/types.py
  • src/snakemake/cli.py
  • src/snakemake/workflow.py
  • tests/tests.py
  • src/snakemake/api.py
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.py`: Do not try to improve formatting. Do not suggest type annotations for...

**/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

⚙️ Source: CodeRabbit Configuration File

List of files the instruction was applied to:

  • src/snakemake/logging.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:1250-1251
Timestamp: 2024-08-13T16:22:58.430Z
Learning: Avoid commenting on trailing commas in code reviews for the Snakemake repository as per the user's preference.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:1250-1251
Timestamp: 2024-10-08T17:41:54.542Z
Learning: Avoid commenting on trailing commas in code reviews for the Snakemake repository as per the user's preference.
Learnt from: johanneskoester
PR: snakemake/snakemake#3117
File: tests/test_wrapper/Snakefile:11-11
Timestamp: 2024-10-06T14:09:54.370Z
Learning: Changes made within test cases, such as in `tests/test_wrapper/Snakefile`, are for testing purposes and do not require updates to the project documentation.
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:20-20
Timestamp: 2025-01-13T18:50:40.791Z
Learning: Dependencies for Snakemake are managed through test-environment.yml file, which includes snakemake-interface-logger-plugins (>= 0.1.0) and other required packages.
Learnt from: leoschwarz
PR: snakemake/snakemake#3176
File: tests/test_output_index.py:99-157
Timestamp: 2025-01-17T12:00:09.368Z
Learning: New test dependencies for Snakemake should be introduced in separate PRs rather than being added as part of feature or refactoring PRs.
Learnt from: mbhall88
PR: snakemake/snakemake#3188
File: tests/test_script/scripts/test.sh:4-4
Timestamp: 2024-11-07T00:32:44.137Z
Learning: In test scripts within the Snakemake project, concise code is preferred over verbose error handling when simplicity suffices.
src/snakemake/logging.py (3)
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:806-830
Timestamp: 2024-09-30T17:17:37.360Z
Learning: In the Snakemake project's `Logger.handler` method, the mapping of the custom log level `'info'` to `_logging.WARNING` is intentional to preserve the existing log output coloring.
Learnt from: johanneskoester
PR: snakemake/snakemake#3107
File: snakemake/logging.py:510-515
Timestamp: 2025-01-14T14:04:30.554Z
Learning: In Snakemake's logging handlers, KeyboardInterrupt and SystemExit exceptions should be ignored (pass) rather than re-raised, as these are control flow signals that should not disrupt the logging process. The exception variable in the final except block should be kept for potential debugging purposes.
Learnt from: johanneskoester
PR: snakemake/snakemake#3114
File: snakemake/cli.py:708-708
Timestamp: 2024-10-13T14:10:37.796Z
Learning: In the `snakemake/cli.py` file, `ExecutorPluginRegistry()` is a singleton class, so multiple instantiations are acceptable and do not cause unnecessary overhead.
🪛 Ruff (0.11.9)
src/snakemake/logging.py

414-417: Return the condition event != LogEvent.WORKFLOW_STARTED directly

Replace with return event != LogEvent.WORKFLOW_STARTED

(SIM103)


651-651: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: tests (10, macos-latest, py312)
  • GitHub Check: tests (8, windows-latest, py312)
  • GitHub Check: tests (7, ubuntu-latest, py312)
  • GitHub Check: tests (7, ubuntu-latest, py311)
  • GitHub Check: tests (6, ubuntu-latest, py311)
  • GitHub Check: tests (6, ubuntu-latest, py312)
  • GitHub Check: tests (3, macos-latest, py312)
  • GitHub Check: tests (3, windows-latest, py312)
  • GitHub Check: tests (2, windows-latest, py312)
🔇 Additional comments (5)
src/snakemake/logging.py (5)

455-455: LGTM! Simplified color determination logic.

The removal of mode dependency from color determination aligns well with the PR's objective of decoupling execution modes from logging internals.


462-479: LGTM! Clean simplification of color detection logic.

The removal of mode-based logic makes the color detection more straightforward while maintaining the essential functionality for determining TTY color support.


557-594: LGTM! Excellent refactoring of handler setup logic.

The replacement of mode-based logic with explicit boolean settings greatly improves code clarity and maintainability. The conditional queue listener setup based on settings.enable_queue_listener aligns perfectly with the PR's goal of reducing overhead when plugins are not used.


644-644: LGTM! Consistent use of settings flags.

The change from mode-based checks to settings.enable_file_logging improves consistency with the overall refactoring approach.


655-672: LGTM! Enhanced flexibility with dynamic log directory handling.

The addition of the optional workdir parameter and dynamic log directory path determination improves the method's flexibility while maintaining backward compatibility. The immediate handler addition to the logger aligns well with the centralized setup approach.

Copy link
Copy Markdown
Contributor

@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: 0

🧹 Nitpick comments (2)
src/snakemake/logging.py (2)

414-416: Simplify the conditional logic.

The if/else structure can be simplified by returning the condition directly, as suggested by the static analysis tool.

-        if event == LogEvent.WORKFLOW_STARTED:
-            return False
-
-        return True
+        return event != LogEvent.WORKFLOW_STARTED

654-654: Optimize dictionary key iteration.

Use direct key membership check instead of iterating over .keys() for better performance.

-            for handler in self.logfile_handlers.keys():
+            for handler in self.logfile_handlers:
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85578b6 and b1f652e.

📒 Files selected for processing (1)
  • src/snakemake/logging.py (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.py`: Do not try to improve formatting. Do not suggest type annotations for...

**/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

⚙️ Source: CodeRabbit Configuration File

List of files the instruction was applied to:

  • src/snakemake/logging.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:1250-1251
Timestamp: 2024-08-13T16:22:58.430Z
Learning: Avoid commenting on trailing commas in code reviews for the Snakemake repository as per the user's preference.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:1250-1251
Timestamp: 2024-10-08T17:41:54.542Z
Learning: Avoid commenting on trailing commas in code reviews for the Snakemake repository as per the user's preference.
Learnt from: johanneskoester
PR: snakemake/snakemake#3117
File: tests/test_wrapper/Snakefile:11-11
Timestamp: 2024-10-06T14:09:54.370Z
Learning: Changes made within test cases, such as in `tests/test_wrapper/Snakefile`, are for testing purposes and do not require updates to the project documentation.
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:20-20
Timestamp: 2025-01-13T18:50:40.791Z
Learning: Dependencies for Snakemake are managed through test-environment.yml file, which includes snakemake-interface-logger-plugins (>= 0.1.0) and other required packages.
Learnt from: leoschwarz
PR: snakemake/snakemake#3176
File: tests/test_output_index.py:99-157
Timestamp: 2025-01-17T12:00:09.368Z
Learning: New test dependencies for Snakemake should be introduced in separate PRs rather than being added as part of feature or refactoring PRs.
Learnt from: mbhall88
PR: snakemake/snakemake#3188
File: tests/test_script/scripts/test.sh:4-4
Timestamp: 2024-11-07T00:32:44.137Z
Learning: In test scripts within the Snakemake project, concise code is preferred over verbose error handling when simplicity suffices.
src/snakemake/logging.py (3)
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:806-830
Timestamp: 2024-09-30T17:17:37.360Z
Learning: In the Snakemake project's `Logger.handler` method, the mapping of the custom log level `'info'` to `_logging.WARNING` is intentional to preserve the existing log output coloring.
Learnt from: johanneskoester
PR: snakemake/snakemake#3107
File: snakemake/logging.py:510-515
Timestamp: 2025-01-14T14:04:30.554Z
Learning: In Snakemake's logging handlers, KeyboardInterrupt and SystemExit exceptions should be ignored (pass) rather than re-raised, as these are control flow signals that should not disrupt the logging process. The exception variable in the final except block should be kept for potential debugging purposes.
Learnt from: johanneskoester
PR: snakemake/snakemake#3114
File: snakemake/cli.py:708-708
Timestamp: 2024-10-13T14:10:37.796Z
Learning: In the `snakemake/cli.py` file, `ExecutorPluginRegistry()` is a singleton class, so multiple instantiations are acceptable and do not cause unnecessary overhead.
🪛 Ruff (0.11.9)
src/snakemake/logging.py

414-417: Return the condition event != LogEvent.WORKFLOW_STARTED directly

Replace with return event != LogEvent.WORKFLOW_STARTED

(SIM103)


654-654: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

⏰ Context from checks skipped due to timeout of 90000ms (35)
  • GitHub Check: tests (8, ubuntu-latest, py311)
  • GitHub Check: tests (9, windows-latest, py312)
  • GitHub Check: tests (10, ubuntu-latest, py312)
  • GitHub Check: tests (9, ubuntu-latest, py312)
  • GitHub Check: tests (10, ubuntu-latest, py311)
  • GitHub Check: tests (10, windows-latest, py312)
  • GitHub Check: tests (9, ubuntu-latest, py311)
  • GitHub Check: tests (8, ubuntu-latest, py312)
  • GitHub Check: tests (8, macos-latest, py312)
  • GitHub Check: tests (8, windows-latest, py312)
  • GitHub Check: tests (7, ubuntu-latest, py312)
  • GitHub Check: tests (6, ubuntu-latest, py311)
  • GitHub Check: tests (7, windows-latest, py312)
  • GitHub Check: tests (7, macos-latest, py312)
  • GitHub Check: tests (2, windows-latest, py312)
  • GitHub Check: tests (7, ubuntu-latest, py311)
  • GitHub Check: tests (6, windows-latest, py312)
  • GitHub Check: tests (4, windows-latest, py312)
  • GitHub Check: tests (5, windows-latest, py312)
  • GitHub Check: tests (6, ubuntu-latest, py312)
  • GitHub Check: tests (5, ubuntu-latest, py311)
  • GitHub Check: tests (5, ubuntu-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py312)
  • GitHub Check: tests (3, windows-latest, py312)
  • GitHub Check: tests (4, macos-latest, py312)
  • GitHub Check: tests (3, ubuntu-latest, py311)
  • GitHub Check: tests (4, ubuntu-latest, py311)
  • GitHub Check: tests (3, ubuntu-latest, py312)
  • GitHub Check: tests (2, macos-latest, py312)
  • GitHub Check: tests (1, windows-latest, py312)
  • GitHub Check: tests (2, ubuntu-latest, py312)
  • GitHub Check: tests (1, macos-latest, py312)
  • GitHub Check: tests (2, ubuntu-latest, py311)
  • GitHub Check: tests (1, ubuntu-latest, py312)
  • GitHub Check: tests (1, ubuntu-latest, py311)
🔇 Additional comments (7)
src/snakemake/logging.py (7)

455-455: LGTM! Simplified color detection logic.

The removal of the mode parameter simplifies the color detection logic and aligns with the overall refactoring to remove mode dependencies.


462-479: LGTM! Cleaner TTY color detection.

The simplified can_color_tty method removes mode-specific logic while maintaining the same color detection behavior. The logic correctly handles "dumb" terminals and TTY detection on non-Windows systems.


542-542: LGTM! Simplified LoggerManager initialization.

The removal of the initialized and mode attributes aligns with the centralized logger setup approach described in the PR objectives.


557-597: LGTM! Improved settings-based configuration.

The refactoring from mode-based to settings-based configuration is well-implemented:

  • Clear separation of stream handlers and other handlers
  • Proper conditional logic for different logging scenarios
  • Queue listener is only created when needed (settings.enable_queue_listener and other_handlers exist)
  • Direct handler addition to logger instead of collecting first

This change improves flexibility and reduces overhead when queue listeners aren't required.


647-647: LGTM! Settings-based logfile hint logic.

The change from mode-based to settings-based check (settings.enable_file_logging) is consistent with the overall refactoring approach.


653-653: LGTM! Settings-based cleanup logic.

The change to use settings.enable_file_logging instead of mode checks is consistent with the refactoring approach.


658-675: LGTM! Enhanced logfile setup with workdir support.

The addition of the optional workdir parameter enhances flexibility by allowing dynamic log directory determination. The implementation:

  • Correctly handles both cases (with and without workdir)
  • Uses os.path.join for proper path construction
  • Creates directories with exist_ok=True to avoid errors
  • Immediately adds the handler to the logger
  • Properly handles OSError exceptions

This change supports the centralized logger setup mentioned in the PR objectives.

@johanneskoester
Copy link
Copy Markdown
Contributor

Is this ready to merge?

@cademirch
Copy link
Copy Markdown
Contributor Author

Is this ready to merge?

Almost! I'm going to add some more tests and finally write some docs on the logging.

Copy link
Copy Markdown
Contributor

@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 (3)
src/snakemake/logging.py (2)

414-416: New filter condition for WORKFLOW_STARTED events.

The logic correctly filters out WORKFLOW_STARTED events. Consider the static analysis suggestion to simplify:

-        if event == LogEvent.WORKFLOW_STARTED:
-            return False
+        return event != LogEvent.WORKFLOW_STARTED

654-657: Settings-based cleanup logic with minor optimization opportunity.

The conversion to settings.enable_file_logging is consistent with the refactoring approach. Consider the static analysis suggestion for line 655:

-        for handler in self.logfile_handlers.keys():
+        for handler in self.logfile_handlers:
tests/test_logging.py (1)

1-21: Clean up unused imports.

Several imports are flagged as unused by static analysis. Consider removing the clearly unused ones to keep the imports clean:

-import pytest
-from .common import run, dpath, apptainer, connected
+from .common import run, dpath
-from .conftest import (
-    skip_on_windows,
-    only_on_windows,
-    ON_WINDOWS,
-    needs_strace,
-    ON_MACOS,
-)
+from .conftest import ON_WINDOWS
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c4e63e and adc3276.

📒 Files selected for processing (13)
  • src/snakemake/cli.py (2 hunks)
  • src/snakemake/logging.py (4 hunks)
  • src/snakemake/settings/types.py (1 hunks)
  • tests/logging/test_logging_config/Snakefile (1 hunks)
  • tests/logging/test_logging_config/results/0.txt (1 hunks)
  • tests/logging/test_logging_config/results/1.txt (1 hunks)
  • tests/logging/test_logging_config/results/2.txt (1 hunks)
  • tests/logging/test_logging_config/results/3.txt (1 hunks)
  • tests/logging/test_logging_config/results/4.txt (1 hunks)
  • tests/logging/test_rule_failure/Snakefile (1 hunks)
  • tests/logging/test_workflow_logger/Snakefile (1 hunks)
  • tests/test_logging.py (1 hunks)
  • tests/tests.py (0 hunks)
💤 Files with no reviewable changes (1)
  • tests/tests.py
✅ Files skipped from review due to trivial changes (5)
  • tests/logging/test_logging_config/results/4.txt
  • tests/logging/test_logging_config/results/2.txt
  • tests/logging/test_logging_config/results/3.txt
  • tests/logging/test_logging_config/results/0.txt
  • tests/logging/test_logging_config/results/1.txt
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/snakemake/settings/types.py
  • src/snakemake/cli.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit Configuration File

**/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

Files:

  • tests/test_logging.py
  • src/snakemake/logging.py
🧠 Learnings (6)
📓 Common learnings
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:1250-1251
Timestamp: 2024-08-13T16:22:58.430Z
Learning: Avoid commenting on trailing commas in code reviews for the Snakemake repository as per the user's preference.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:1250-1251
Timestamp: 2024-10-08T17:41:54.542Z
Learning: Avoid commenting on trailing commas in code reviews for the Snakemake repository as per the user's preference.
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:20-20
Timestamp: 2025-01-13T18:50:40.791Z
Learning: Dependencies for Snakemake are managed through test-environment.yml file, which includes snakemake-interface-logger-plugins (>= 0.1.0) and other required packages.
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:806-830
Timestamp: 2024-09-30T17:17:37.360Z
Learning: In the Snakemake project's `Logger.handler` method, the mapping of the custom log level `'info'` to `_logging.WARNING` is intentional to preserve the existing log output coloring.
Learnt from: johanneskoester
PR: snakemake/snakemake#2963
File: snakemake/scheduler.py:199-199
Timestamp: 2024-08-27T14:31:21.449Z
Learning: In the Snakemake project, do not suggest adding trailing commas in multi-line logging statements, as Black autoformatter handles this.
Learnt from: johanneskoester
PR: snakemake/snakemake#2963
File: snakemake/scheduler.py:199-199
Timestamp: 2024-10-08T17:41:54.542Z
Learning: In the Snakemake project, do not suggest adding trailing commas in multi-line logging statements, as Black autoformatter handles this.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:0-0
Timestamp: 2024-08-13T16:07:33.369Z
Learning: In the Snakemake project, trailing commas are not needed in logger messages if Black formatting is used, as it doesn't require them in such contexts.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:0-0
Timestamp: 2024-10-08T17:41:54.542Z
Learning: In the Snakemake project, trailing commas are not needed in logger messages if Black formatting is used, as it doesn't require them in such contexts.
tests/logging/test_rule_failure/Snakefile (8)

Learnt from: johanneskoester
PR: #3117
File: tests/test_wrapper/Snakefile:11-11
Timestamp: 2024-10-06T14:09:54.370Z
Learning: Changes made within test cases, such as in tests/test_wrapper/Snakefile, are for testing purposes and do not require updates to the project documentation.

Learnt from: johanneskoester
PR: #2925
File: tests/test_nonstr_params/Snakefile:14-15
Timestamp: 2024-12-21T15:10:31.992Z
Learning: The file "test.jsonl" in tests/test_nonstr_params is automatically created by Snakemake, rather than manually generated in the Snakefile.

Learnt from: leoschwarz
PR: #3176
File: tests/test_output_index.py:99-157
Timestamp: 2025-01-17T12:00:09.368Z
Learning: New test dependencies for Snakemake should be introduced in separate PRs rather than being added as part of feature or refactoring PRs.

Learnt from: mbhall88
PR: #3188
File: tests/test_script/scripts/test.sh:4-4
Timestamp: 2024-11-07T00:32:44.137Z
Learning: In test scripts within the Snakemake project, concise code is preferred over verbose error handling when simplicity suffices.

Learnt from: johanneskoester
PR: #3204
File: tests/test_cores_cluster/qsub:1-6
Timestamp: 2024-11-12T20:22:54.184Z
Learning: In the Snakemake codebase, the tests/test_cores_cluster/qsub script is a dummy script for testing, and input validation and error handling are not required in such scripts.

Learnt from: johanneskoester
PR: #2985
File: tests/tests.py:2051-2051
Timestamp: 2024-08-13T09:25:24.046Z
Learning: In the Snakemake repository, avoid suggesting return type annotations for test functions.

Learnt from: johanneskoester
PR: #2985
File: tests/tests.py:2051-2051
Timestamp: 2024-10-08T17:41:54.542Z
Learning: In the Snakemake repository, avoid suggesting return type annotations for test functions.

Learnt from: johanneskoester
PR: #2927
File: tests/test_subpath/Snakefile:11-11
Timestamp: 2024-12-14T13:10:48.450Z
Learning: In Snakemake, when a rule defines a single output file (even if the output is specified as a dictionary), {output} in the shell command can be used directly to refer to that file.

tests/logging/test_workflow_logger/Snakefile (10)

Learnt from: johanneskoester
PR: #3117
File: tests/test_wrapper/Snakefile:11-11
Timestamp: 2024-10-06T14:09:54.370Z
Learning: Changes made within test cases, such as in tests/test_wrapper/Snakefile, are for testing purposes and do not require updates to the project documentation.

Learnt from: johanneskoester
PR: #2925
File: tests/test_nonstr_params/Snakefile:14-15
Timestamp: 2024-12-21T15:10:31.992Z
Learning: The file "test.jsonl" in tests/test_nonstr_params is automatically created by Snakemake, rather than manually generated in the Snakefile.

Learnt from: cademirch
PR: #3107
File: snakemake/logging.py:20-20
Timestamp: 2025-01-13T18:50:40.791Z
Learning: Dependencies for Snakemake are managed through test-environment.yml file, which includes snakemake-interface-logger-plugins (>= 0.1.0) and other required packages.

Learnt from: leoschwarz
PR: #3176
File: tests/test_output_index.py:99-157
Timestamp: 2025-01-17T12:00:09.368Z
Learning: New test dependencies for Snakemake should be introduced in separate PRs rather than being added as part of feature or refactoring PRs.

Learnt from: cademirch
PR: #3107
File: snakemake/logging.py:806-830
Timestamp: 2024-09-30T17:17:37.360Z
Learning: In the Snakemake project's Logger.handler method, the mapping of the custom log level 'info' to _logging.WARNING is intentional to preserve the existing log output coloring.

Learnt from: mbhall88
PR: #3188
File: tests/test_script/scripts/test.sh:4-4
Timestamp: 2024-11-07T00:32:44.137Z
Learning: In test scripts within the Snakemake project, concise code is preferred over verbose error handling when simplicity suffices.

Learnt from: johanneskoester
PR: #3159
File: docs/tutorial/interaction_visualization_reporting/workdir/workflow/Snakefile:1-1
Timestamp: 2024-10-20T19:42:16.694Z
Learning: The report directive at the workflow level is still valid in Snakemake and is not deprecated.

Learnt from: johanneskoester
PR: #2985
File: tests/tests.py:2051-2051
Timestamp: 2024-10-08T17:41:54.542Z
Learning: In the Snakemake repository, avoid suggesting return type annotations for test functions.

Learnt from: johanneskoester
PR: #2985
File: tests/tests.py:2051-2051
Timestamp: 2024-08-13T09:25:24.046Z
Learning: In the Snakemake repository, avoid suggesting return type annotations for test functions.

Learnt from: johanneskoester
PR: #2963
File: snakemake/scheduler.py:199-199
Timestamp: 2024-08-27T14:31:21.449Z
Learning: In the Snakemake project, do not suggest adding trailing commas in multi-line logging statements, as Black autoformatter handles this.

tests/test_logging.py (6)

Learnt from: johanneskoester
PR: #3117
File: tests/test_wrapper/Snakefile:11-11
Timestamp: 2024-10-06T14:09:54.370Z
Learning: Changes made within test cases, such as in tests/test_wrapper/Snakefile, are for testing purposes and do not require updates to the project documentation.

Learnt from: leoschwarz
PR: #3176
File: tests/test_output_index.py:99-157
Timestamp: 2025-01-17T12:00:09.368Z
Learning: New test dependencies for Snakemake should be introduced in separate PRs rather than being added as part of feature or refactoring PRs.

Learnt from: cademirch
PR: #3107
File: snakemake/logging.py:20-20
Timestamp: 2025-01-13T18:50:40.791Z
Learning: Dependencies for Snakemake are managed through test-environment.yml file, which includes snakemake-interface-logger-plugins (>= 0.1.0) and other required packages.

Learnt from: johanneskoester
PR: #2925
File: tests/test_nonstr_params/Snakefile:14-15
Timestamp: 2024-12-21T15:10:31.992Z
Learning: The file "test.jsonl" in tests/test_nonstr_params is automatically created by Snakemake, rather than manually generated in the Snakefile.

Learnt from: johanneskoester
PR: #3135
File: snakemake/profiles.py:54-55
Timestamp: 2024-10-13T14:29:38.902Z
Learning: In the Snakemake test suite, tests for configuration keys like 'group-components' may already be covered within existing tests for 'groups'. Ensure to verify this before suggesting additional tests.

Learnt from: mbhall88
PR: #3188
File: tests/test_script/scripts/test.sh:4-4
Timestamp: 2024-11-07T00:32:44.137Z
Learning: In test scripts within the Snakemake project, concise code is preferred over verbose error handling when simplicity suffices.

tests/logging/test_logging_config/Snakefile (10)

Learnt from: johanneskoester
PR: #3117
File: tests/test_wrapper/Snakefile:11-11
Timestamp: 2024-10-06T14:09:54.370Z
Learning: Changes made within test cases, such as in tests/test_wrapper/Snakefile, are for testing purposes and do not require updates to the project documentation.

Learnt from: johanneskoester
PR: #2925
File: tests/test_nonstr_params/Snakefile:14-15
Timestamp: 2024-12-21T15:10:31.992Z
Learning: The file "test.jsonl" in tests/test_nonstr_params is automatically created by Snakemake, rather than manually generated in the Snakefile.

Learnt from: cademirch
PR: #3107
File: snakemake/logging.py:20-20
Timestamp: 2025-01-13T18:50:40.791Z
Learning: Dependencies for Snakemake are managed through test-environment.yml file, which includes snakemake-interface-logger-plugins (>= 0.1.0) and other required packages.

Learnt from: leoschwarz
PR: #3176
File: tests/test_output_index.py:99-157
Timestamp: 2025-01-17T12:00:09.368Z
Learning: New test dependencies for Snakemake should be introduced in separate PRs rather than being added as part of feature or refactoring PRs.

Learnt from: cademirch
PR: #3107
File: snakemake/logging.py:806-830
Timestamp: 2024-09-30T17:17:37.360Z
Learning: In the Snakemake project's Logger.handler method, the mapping of the custom log level 'info' to _logging.WARNING is intentional to preserve the existing log output coloring.

Learnt from: johanneskoester
PR: #3135
File: snakemake/profiles.py:54-55
Timestamp: 2024-10-13T14:29:38.902Z
Learning: In the Snakemake test suite, tests for configuration keys like 'group-components' may already be covered within existing tests for 'groups'. Ensure to verify this before suggesting additional tests.

Learnt from: johanneskoester
PR: #2963
File: snakemake/scheduler.py:199-199
Timestamp: 2024-08-27T14:31:21.449Z
Learning: In the Snakemake project, do not suggest adding trailing commas in multi-line logging statements, as Black autoformatter handles this.

Learnt from: johanneskoester
PR: #2963
File: snakemake/scheduler.py:199-199
Timestamp: 2024-10-08T17:41:54.542Z
Learning: In the Snakemake project, do not suggest adding trailing commas in multi-line logging statements, as Black autoformatter handles this.

Learnt from: mbhall88
PR: #3188
File: tests/test_script/scripts/test.sh:4-4
Timestamp: 2024-11-07T00:32:44.137Z
Learning: In test scripts within the Snakemake project, concise code is preferred over verbose error handling when simplicity suffices.

Learnt from: johanneskoester
PR: #2985
File: tests/tests.py:2051-2051
Timestamp: 2024-08-13T09:25:24.046Z
Learning: In the Snakemake repository, avoid suggesting return type annotations for test functions.

src/snakemake/logging.py (3)

Learnt from: cademirch
PR: #3107
File: snakemake/logging.py:806-830
Timestamp: 2024-09-30T17:17:37.360Z
Learning: In the Snakemake project's Logger.handler method, the mapping of the custom log level 'info' to _logging.WARNING is intentional to preserve the existing log output coloring.

Learnt from: johanneskoester
PR: #3107
File: snakemake/logging.py:510-515
Timestamp: 2025-01-14T14:04:30.554Z
Learning: In Snakemake's logging handlers, KeyboardInterrupt and SystemExit exceptions should be ignored (pass) rather than re-raised, as these are control flow signals that should not disrupt the logging process. The exception variable in the final except block should be kept for potential debugging purposes.

Learnt from: johanneskoester
PR: #3114
File: snakemake/cli.py:708-708
Timestamp: 2024-10-13T14:10:37.796Z
Learning: In the snakemake/cli.py file, ExecutorPluginRegistry() is a singleton class, so multiple instantiations are acceptable and do not cause unnecessary overhead.

🪛 Ruff (0.12.2)
tests/test_logging.py

5-5: pytest imported but unused

Remove unused import: pytest

(F401)


13-13: .common.apptainer imported but unused

Remove unused import

(F401)


13-13: .common.connected imported but unused

Remove unused import

(F401)


15-15: .conftest.skip_on_windows imported but unused

Remove unused import

(F401)


16-16: .conftest.only_on_windows imported but unused

Remove unused import

(F401)


18-18: .conftest.needs_strace imported but unused

Remove unused import

(F401)


19-19: .conftest.ON_MACOS imported but unused

Remove unused import

(F401)

src/snakemake/logging.py

414-417: Return the condition event != LogEvent.WORKFLOW_STARTED directly

Replace with return event != LogEvent.WORKFLOW_STARTED

(SIM103)


655-655: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (36)
  • GitHub Check: apidocs
  • GitHub Check: tests (8, windows-latest, py312)
  • GitHub Check: tests (5, windows-latest, py312)
  • GitHub Check: tests (10, ubuntu-latest, py311)
  • GitHub Check: tests (9, ubuntu-latest, py312)
  • GitHub Check: tests (10, windows-latest, py312)
  • GitHub Check: tests (9, windows-latest, py312)
  • GitHub Check: tests (9, ubuntu-latest, py311)
  • GitHub Check: tests (10, ubuntu-latest, py312)
  • GitHub Check: tests (7, ubuntu-latest, py312)
  • GitHub Check: tests (10, macos-latest, py312)
  • GitHub Check: tests (6, ubuntu-latest, py311)
  • GitHub Check: tests (7, windows-latest, py312)
  • GitHub Check: tests (8, ubuntu-latest, py311)
  • GitHub Check: tests (7, ubuntu-latest, py311)
  • GitHub Check: tests (8, ubuntu-latest, py312)
  • GitHub Check: tests (6, windows-latest, py312)
  • GitHub Check: tests (6, ubuntu-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py311)
  • GitHub Check: tests (6, macos-latest, py312)
  • GitHub Check: tests (5, ubuntu-latest, py312)
  • GitHub Check: tests (4, macos-latest, py312)
  • GitHub Check: tests (4, windows-latest, py312)
  • GitHub Check: tests (2, macos-latest, py312)
  • GitHub Check: tests (3, ubuntu-latest, py311)
  • GitHub Check: tests (5, macos-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py312)
  • GitHub Check: tests (3, ubuntu-latest, py312)
  • GitHub Check: tests (3, windows-latest, py312)
  • GitHub Check: tests (5, ubuntu-latest, py311)
  • GitHub Check: tests (2, ubuntu-latest, py311)
  • GitHub Check: tests (1, windows-latest, py312)
  • GitHub Check: tests (1, ubuntu-latest, py312)
  • GitHub Check: tests (2, windows-latest, py312)
  • GitHub Check: tests (2, ubuntu-latest, py312)
  • GitHub Check: tests (1, ubuntu-latest, py311)
🔇 Additional comments (18)
tests/logging/test_workflow_logger/Snakefile (3)

1-6: Effective test for logger availability in Snakefile context.

This test correctly validates that the logger is accessible within a Snakefile after the centralized logging setup changes. The code assumes logger is available in the global scope, which aligns with the PR's objective to enable workflow files to utilize the logger.


9-11: Standard workflow entry point.

The all rule is correctly defined and follows Snakemake conventions for specifying workflow targets.


14-18: Correct rule implementation for test scenario.

Rule a properly uses wildcards and shell commands to generate the expected test outputs.

tests/logging/test_rule_failure/Snakefile (2)

1-3: Standard workflow entry point.

The all rule correctly defines the workflow targets using proper Snakemake syntax.


6-10: Intentional error for failure testing.

The typo eho instead of echo is deliberately included to trigger rule failure and test error logging behavior. This design effectively serves the test's purpose.

tests/logging/test_logging_config/Snakefile (3)

1-28: Well-structured logging configuration for testing.

The logging configuration dictionary is comprehensive and correctly formatted:

  • Uses proper dictConfig version 1 format
  • Custom formatter includes test identifier [TESTLOGGINGCONFIG] for verification
  • Console handler redirects to stdout as needed for test validation
  • Snakemake logger is properly configured with DEBUG level and disabled propagation

29-31: Standard workflow entry point.

The all rule follows standard Snakemake conventions for defining workflow targets.


34-38: Correct rule implementation.

Rule a properly implements the pattern for generating test output files using wildcards and shell commands.

src/snakemake/logging.py (5)

455-456: Simplified constructor logic.

Good simplification removing the mode parameter dependency. The nocolor determination now relies solely on TTY capability detection, making the logic cleaner.


462-480: Improved TTY color detection logic.

The simplified method now focuses on actual terminal capabilities rather than execution mode. This provides more accurate color support determination based on real TTY status and terminal type.


547-600: Excellent refactoring of logger setup logic.

This refactoring successfully:

  • Removes mode dependency in favor of settings-based configuration
  • Handles error-only logging with early return for better performance
  • Validates plugin handlers to prevent conflicts
  • Sets up asynchronous logging only when plugin handlers exist
  • Ensures proper fallback to default handlers

The centralized approach aligns well with the PR's objectives to simplify logging management.


647-651: Consistent settings-based logic.

Good conversion from mode-based to settings-based logic using settings.enable_file_logging. This maintains the same functionality while aligning with the refactoring approach.


659-680: Enhanced logfile setup with dynamic directory support.

The addition of the optional workdir parameter provides better flexibility for log file placement. The immediate handler addition and simplified logic make the method more straightforward and maintainable.

tests/test_logging.py (5)

23-48: Comprehensive logfile functionality test.

Excellent test coverage for:

  • Log directory creation validation
  • Log file generation verification
  • Log content assertion with specific completion message
  • Proper cleanup with Windows compatibility

The test structure is clear and assertions are meaningful.


50-64: Effective custom logging configuration test.

Good test design that validates custom logging configuration in Snakefiles. The subprocess approach and assertion of the custom tag [TESTLOGGINGCONFIG] effectively verifies the logging setup functionality.


66-101: Critical test for workflow logger integration.

This test validates a key PR objective - enabling logger usage within workflow files. The dual validation approach (checking both Snakemake logs and custom log file) provides comprehensive coverage of the logger accessibility feature.


103-127: Detailed log event validation for dry run mode.

Excellent granular testing of log events with precise count expectations. This provides valuable regression protection for the logging event system during dry run execution.


129-178: Comprehensive log event validation for full execution.

Outstanding test coverage that validates:

  • Expected log event counts across multiple event types
  • Absence of unexpected log events (important for regression detection)
  • Stderr output content verification
  • Integration between different logging mechanisms

This provides robust protection against logging regressions.

Comment thread tests/test_logging.py
Copy link
Copy Markdown
Contributor

@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: 0

♻️ Duplicate comments (1)
tests/test_logging.py (1)

180-181: Complete the rule failure test implementation.

This test function is missing assertions and validation logic for rule failure logging behavior, as noted in previous reviews.

🧹 Nitpick comments (1)
tests/test_logging.py (1)

5-5: Clean up unused imports.

Several imports are not used in this file and can be removed to improve code clarity.

-import pytest
 import logging
 from collections import Counter
 from snakemake_interface_logger_plugins.common import LogEvent


 sys.path.insert(0, os.path.dirname(__file__))

-from .common import run, dpath, apptainer, connected
+from .common import run, dpath
 from .conftest import (
-    skip_on_windows,
-    only_on_windows,
     ON_WINDOWS,
-    needs_strace,
-    ON_MACOS,
 )

Also applies to: 13-13, 15-16, 18-19

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between adc3276 and 2d99be4.

📒 Files selected for processing (2)
  • src/snakemake/settings/types.py (1 hunks)
  • tests/test_logging.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/snakemake/settings/types.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit Configuration File

**/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

Files:

  • tests/test_logging.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:1250-1251
Timestamp: 2024-08-13T16:22:58.430Z
Learning: Avoid commenting on trailing commas in code reviews for the Snakemake repository as per the user's preference.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:1250-1251
Timestamp: 2024-10-08T17:41:54.542Z
Learning: Avoid commenting on trailing commas in code reviews for the Snakemake repository as per the user's preference.
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:20-20
Timestamp: 2025-01-13T18:50:40.791Z
Learning: Dependencies for Snakemake are managed through test-environment.yml file, which includes snakemake-interface-logger-plugins (>= 0.1.0) and other required packages.
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:806-830
Timestamp: 2024-09-30T17:17:37.360Z
Learning: In the Snakemake project's `Logger.handler` method, the mapping of the custom log level `'info'` to `_logging.WARNING` is intentional to preserve the existing log output coloring.
Learnt from: johanneskoester
PR: snakemake/snakemake#2963
File: snakemake/scheduler.py:199-199
Timestamp: 2024-08-27T14:31:21.449Z
Learning: In the Snakemake project, do not suggest adding trailing commas in multi-line logging statements, as Black autoformatter handles this.
Learnt from: johanneskoester
PR: snakemake/snakemake#2963
File: snakemake/scheduler.py:199-199
Timestamp: 2024-10-08T17:41:54.542Z
Learning: In the Snakemake project, do not suggest adding trailing commas in multi-line logging statements, as Black autoformatter handles this.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:0-0
Timestamp: 2024-08-13T16:07:33.369Z
Learning: In the Snakemake project, trailing commas are not needed in logger messages if Black formatting is used, as it doesn't require them in such contexts.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:0-0
Timestamp: 2024-10-08T17:41:54.542Z
Learning: In the Snakemake project, trailing commas are not needed in logger messages if Black formatting is used, as it doesn't require them in such contexts.
tests/test_logging.py (6)

Learnt from: johanneskoester
PR: #3117
File: tests/test_wrapper/Snakefile:11-11
Timestamp: 2024-10-06T14:09:54.370Z
Learning: Changes made within test cases, such as in tests/test_wrapper/Snakefile, are for testing purposes and do not require updates to the project documentation.

Learnt from: leoschwarz
PR: #3176
File: tests/test_output_index.py:99-157
Timestamp: 2025-01-17T12:00:09.368Z
Learning: New test dependencies for Snakemake should be introduced in separate PRs rather than being added as part of feature or refactoring PRs.

Learnt from: cademirch
PR: #3107
File: snakemake/logging.py:20-20
Timestamp: 2025-01-13T18:50:40.791Z
Learning: Dependencies for Snakemake are managed through test-environment.yml file, which includes snakemake-interface-logger-plugins (>= 0.1.0) and other required packages.

Learnt from: johanneskoester
PR: #2925
File: tests/test_nonstr_params/Snakefile:14-15
Timestamp: 2024-12-21T15:10:31.992Z
Learning: The file "test.jsonl" in tests/test_nonstr_params is automatically created by Snakemake, rather than manually generated in the Snakefile.

Learnt from: johanneskoester
PR: #3135
File: snakemake/profiles.py:54-55
Timestamp: 2024-10-13T14:29:38.902Z
Learning: In the Snakemake test suite, tests for configuration keys like 'group-components' may already be covered within existing tests for 'groups'. Ensure to verify this before suggesting additional tests.

Learnt from: mbhall88
PR: #3188
File: tests/test_script/scripts/test.sh:4-4
Timestamp: 2024-11-07T00:32:44.137Z
Learning: In test scripts within the Snakemake project, concise code is preferred over verbose error handling when simplicity suffices.

🪛 Ruff (0.12.2)
tests/test_logging.py

5-5: pytest imported but unused

Remove unused import: pytest

(F401)


13-13: .common.apptainer imported but unused

Remove unused import

(F401)


13-13: .common.connected imported but unused

Remove unused import

(F401)


15-15: .conftest.skip_on_windows imported but unused

Remove unused import

(F401)


16-16: .conftest.only_on_windows imported but unused

Remove unused import

(F401)


18-18: .conftest.needs_strace imported but unused

Remove unused import

(F401)


19-19: .conftest.ON_MACOS imported but unused

Remove unused import

(F401)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (35)
  • GitHub Check: tests (8, macos-latest, py312)
  • GitHub Check: tests (10, ubuntu-latest, py311)
  • GitHub Check: tests (10, ubuntu-latest, py312)
  • GitHub Check: tests (8, ubuntu-latest, py311)
  • GitHub Check: tests (10, windows-latest, py312)
  • GitHub Check: tests (9, windows-latest, py312)
  • GitHub Check: tests (9, ubuntu-latest, py311)
  • GitHub Check: tests (6, ubuntu-latest, py311)
  • GitHub Check: tests (8, ubuntu-latest, py312)
  • GitHub Check: tests (8, windows-latest, py312)
  • GitHub Check: tests (9, ubuntu-latest, py312)
  • GitHub Check: tests (7, ubuntu-latest, py311)
  • GitHub Check: tests (6, windows-latest, py312)
  • GitHub Check: tests (7, windows-latest, py312)
  • GitHub Check: tests (7, macos-latest, py312)
  • GitHub Check: tests (6, ubuntu-latest, py312)
  • GitHub Check: tests (6, macos-latest, py312)
  • GitHub Check: tests (5, windows-latest, py312)
  • GitHub Check: tests (4, macos-latest, py312)
  • GitHub Check: tests (7, ubuntu-latest, py312)
  • GitHub Check: tests (5, ubuntu-latest, py312)
  • GitHub Check: tests (3, ubuntu-latest, py311)
  • GitHub Check: tests (3, windows-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py312)
  • GitHub Check: tests (4, windows-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py311)
  • GitHub Check: tests (5, ubuntu-latest, py311)
  • GitHub Check: tests (2, ubuntu-latest, py312)
  • GitHub Check: tests (3, ubuntu-latest, py312)
  • GitHub Check: tests (2, windows-latest, py312)
  • GitHub Check: tests (1, ubuntu-latest, py311)
  • GitHub Check: tests (1, windows-latest, py312)
  • GitHub Check: tests (1, macos-latest, py312)
  • GitHub Check: tests (2, ubuntu-latest, py311)
  • GitHub Check: tests (1, ubuntu-latest, py312)
🔇 Additional comments (5)
tests/test_logging.py (5)

23-48: Well-structured test for log file verification.

The test correctly validates log directory creation, file existence, and content verification. The Windows-specific cleanup handling is appropriate.


50-64: Appropriate test for logging configuration validation.

The test correctly uses subprocess to validate that custom logging configuration produces expected output, even in failure scenarios. The reference to the GitHub issue provides helpful context.


66-101: Comprehensive test for workflow logger functionality.

This test effectively validates that loggers work correctly within workflow files by checking both Snakemake's standard logs and custom log files. The dual validation approach ensures proper logger integration.


103-127: Well-designed test for dry-run log events.

The test effectively validates log event emission during dry-run execution. The use of Counter for event tracking and detailed assertion messages makes it robust and debuggable.


129-178: Comprehensive test for normal execution log events.

The test provides excellent coverage by validating both structured log events and stderr output. The defensive check for unexpected events and detailed assertion messages enhance the test's robustness.

Copy link
Copy Markdown
Contributor

@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: 2

🔭 Outside diff range comments (1)
src/snakemake/logging.py (1)

380-381: Bug: dryrun filter compares wrong field; use event, not levelname

level is the logging level name (e.g., "INFO"), not the Snakemake event. Comparing to "run_info" will likely never match. Use the LogEvent instead.

-        if self.dryrun and level == "run_info":
+        if self.dryrun and event == LogEvent.RUN_INFO:
             return True
🧹 Nitpick comments (1)
src/snakemake/logging.py (1)

414-417: Tidy: return the condition directly (Ruff SIM103)

No functional change; shorter and clearer.

-        if event == LogEvent.WORKFLOW_STARTED:
-            return False
-
-        return True
+        return event != LogEvent.WORKFLOW_STARTED
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd3a18f and 42fdc63.

📒 Files selected for processing (4)
  • docs/project_info/codebase.rst (1 hunks)
  • src/snakemake/cli.py (4 hunks)
  • src/snakemake/logging.py (4 hunks)
  • src/snakemake/settings/types.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/project_info/codebase.rst
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/snakemake/settings/types.py
  • src/snakemake/cli.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit Configuration File

**/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

Files:

  • src/snakemake/logging.py
🧠 Learnings (4)
📓 Common learnings
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:1250-1251
Timestamp: 2024-08-13T16:22:58.430Z
Learning: Avoid commenting on trailing commas in code reviews for the Snakemake repository as per the user's preference.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:1250-1251
Timestamp: 2024-10-08T17:41:54.542Z
Learning: Avoid commenting on trailing commas in code reviews for the Snakemake repository as per the user's preference.
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:20-20
Timestamp: 2025-01-13T18:50:40.791Z
Learning: Dependencies for Snakemake are managed through test-environment.yml file, which includes snakemake-interface-logger-plugins (>= 0.1.0) and other required packages.
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:806-830
Timestamp: 2024-09-30T17:17:37.360Z
Learning: In the Snakemake project's `Logger.handler` method, the mapping of the custom log level `'info'` to `_logging.WARNING` is intentional to preserve the existing log output coloring.
Learnt from: johanneskoester
PR: snakemake/snakemake#2963
File: snakemake/scheduler.py:199-199
Timestamp: 2024-10-08T17:41:54.542Z
Learning: In the Snakemake project, do not suggest adding trailing commas in multi-line logging statements, as Black autoformatter handles this.
Learnt from: johanneskoester
PR: snakemake/snakemake#2963
File: snakemake/scheduler.py:199-199
Timestamp: 2024-08-27T14:31:21.449Z
Learning: In the Snakemake project, do not suggest adding trailing commas in multi-line logging statements, as Black autoformatter handles this.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:0-0
Timestamp: 2024-08-13T16:07:33.369Z
Learning: In the Snakemake project, trailing commas are not needed in logger messages if Black formatting is used, as it doesn't require them in such contexts.
Learnt from: johanneskoester
PR: snakemake/snakemake#3014
File: snakemake/workflow.py:0-0
Timestamp: 2024-10-08T17:41:54.542Z
Learning: In the Snakemake project, trailing commas are not needed in logger messages if Black formatting is used, as it doesn't require them in such contexts.
📚 Learning: 2024-09-30T17:17:37.360Z
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:806-830
Timestamp: 2024-09-30T17:17:37.360Z
Learning: In the Snakemake project's `Logger.handler` method, the mapping of the custom log level `'info'` to `_logging.WARNING` is intentional to preserve the existing log output coloring.

Applied to files:

  • src/snakemake/logging.py
📚 Learning: 2025-01-14T14:04:30.554Z
Learnt from: johanneskoester
PR: snakemake/snakemake#3107
File: snakemake/logging.py:510-515
Timestamp: 2025-01-14T14:04:30.554Z
Learning: In Snakemake's logging handlers, KeyboardInterrupt and SystemExit exceptions should be ignored (pass) rather than re-raised, as these are control flow signals that should not disrupt the logging process. The exception variable in the final except block should be kept for potential debugging purposes.

Applied to files:

  • src/snakemake/logging.py
📚 Learning: 2024-10-13T14:10:37.796Z
Learnt from: johanneskoester
PR: snakemake/snakemake#3114
File: snakemake/cli.py:708-708
Timestamp: 2024-10-13T14:10:37.796Z
Learning: In the `snakemake/cli.py` file, `ExecutorPluginRegistry()` is a singleton class, so multiple instantiations are acceptable and do not cause unnecessary overhead.

Applied to files:

  • src/snakemake/logging.py
🧬 Code Graph Analysis (1)
src/snakemake/logging.py (2)
src/snakemake/workflow.py (2)
  • dryrun (400-404)
  • workdir (1662-1666)
src/snakemake/utils.py (1)
  • makedirs (291-298)
🪛 Ruff (0.12.2)
src/snakemake/logging.py

414-417: Return the condition event != LogEvent.WORKFLOW_STARTED directly

Replace with return event != LogEvent.WORKFLOW_STARTED

(SIM103)


672-672: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (56)
  • GitHub Check: tests (10, ubuntu-latest, py311)
  • GitHub Check: tests (10, windows-latest, py313)
  • GitHub Check: tests (9, ubuntu-latest, py313)
  • GitHub Check: tests (10, ubuntu-latest, py313)
  • GitHub Check: tests (10, ubuntu-latest, py312)
  • GitHub Check: tests (10, windows-latest, py312)
  • GitHub Check: tests (9, ubuntu-latest, py312)
  • GitHub Check: tests (9, ubuntu-latest, py311)
  • GitHub Check: tests (9, windows-latest, py313)
  • GitHub Check: tests (9, windows-latest, py312)
  • GitHub Check: tests (7, windows-latest, py312)
  • GitHub Check: tests (8, windows-latest, py312)
  • GitHub Check: tests (8, windows-latest, py313)
  • GitHub Check: tests (8, ubuntu-latest, py311)
  • GitHub Check: tests (8, ubuntu-latest, py313)
  • GitHub Check: tests (7, ubuntu-latest, py313)
  • GitHub Check: tests (8, ubuntu-latest, py312)
  • GitHub Check: tests (7, windows-latest, py313)
  • GitHub Check: tests (7, ubuntu-latest, py312)
  • GitHub Check: tests (6, windows-latest, py312)
  • GitHub Check: tests (6, ubuntu-latest, py312)
  • GitHub Check: tests (6, windows-latest, py313)
  • GitHub Check: tests (6, ubuntu-latest, py313)
  • GitHub Check: tests (5, windows-latest, py313)
  • GitHub Check: tests (7, ubuntu-latest, py311)
  • GitHub Check: tests (6, ubuntu-latest, py311)
  • GitHub Check: tests (5, ubuntu-latest, py313)
  • GitHub Check: tests (5, macos-latest, py313)
  • GitHub Check: tests (5, windows-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py311)
  • GitHub Check: tests (5, ubuntu-latest, py312)
  • GitHub Check: tests (5, ubuntu-latest, py311)
  • GitHub Check: tests (4, windows-latest, py313)
  • GitHub Check: tests (4, windows-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py313)
  • GitHub Check: tests (4, ubuntu-latest, py312)
  • GitHub Check: tests (2, windows-latest, py312)
  • GitHub Check: tests (3, ubuntu-latest, py313)
  • GitHub Check: tests (3, windows-latest, py313)
  • GitHub Check: tests (2, windows-latest, py313)
  • GitHub Check: tests (2, macos-latest, py312)
  • GitHub Check: tests (3, windows-latest, py312)
  • GitHub Check: tests (2, ubuntu-latest, py313)
  • GitHub Check: tests (3, ubuntu-latest, py311)
  • GitHub Check: tests (3, ubuntu-latest, py312)
  • GitHub Check: tests (2, macos-latest, py313)
  • GitHub Check: tests (1, ubuntu-latest, py311)
  • GitHub Check: tests (2, ubuntu-latest, py312)
  • GitHub Check: tests (2, ubuntu-latest, py311)
  • GitHub Check: tests (1, macos-latest, py313)
  • GitHub Check: tests (1, windows-latest, py312)
  • GitHub Check: tests (1, windows-latest, py313)
  • GitHub Check: tests (1, macos-latest, py312)
  • GitHub Check: tests (1, ubuntu-latest, py313)
  • GitHub Check: tests (1, ubuntu-latest, py312)
  • GitHub Check: apidocs
🔇 Additional comments (7)
src/snakemake/logging.py (7)

513-516: Good: ignore KeyboardInterrupt/SystemExit in emit

Matches Snakemake guidance to treat them as control-flow signals.


462-479: Windows color output now disabled; verify intended UX change

This path disables ANSI colors on Windows entirely. If that’s intentional, fine. If not, consider optionally enabling colors on modern Windows terminals or when colorama is present.

Would you like to maintain color on Windows terminals that support ANSI sequences? If yes, I can propose a minimal, dependency-free detection improvement.


573-617: Plugin queue init LGTM; one stream handler enforcement is good

Queue is only used when plugins exist and single-stream constraint is enforced. Looks solid after addressing listener lifecycle in setup.


665-668: Logfile hint gating LGTM

Using enable_file_logging and not dryrun for hints is correct for the new model.


676-694: Ordering and threading considerations for setup_logfile

  • If setup_logfile() is called before setup(), the file handler will be removed by setup() (handlers are cleared). Ensure call order is setup() then setup_logfile().
  • File handler is attached directly to the logger while plugin handlers are behind a queue; that’s fine if you want immediate file writes outside the queue. If you want all handlers to be fed via the queue for consistent ordering, consider routing the file handler through the queue as well.

Please confirm intended call order and whether file handler should be queued alongside plugin handlers. I can provide a diff for either approach.


390-401: No issue with LogEvent.RESOURCES_INFO availability
The RESOURCES_INFO member is defined in the snakemake_interface_logger_plugins.common.LogEvent enum (included via the snakemake-interface-logger-plugins (>= 0.1.0) dependency). References in both the workflow code and tests/test_logging.py confirm it’s present at import time, so no runtime failure will occur.


558-571: Swap logger setup and logfile initialization in src/snakemake/api.py

Since logger_manager.setup() clears all handlers, it must be called before setup_logfile() to avoid discarding the file handler. In src/snakemake/api.py the calls are currently inverted:

• Line 148:

logger_manager.setup_logfile(workdir=workdir)


• Line 258:

logger_manager.setup(
    handlers=log_handlers,
    settings=self.output_settings,
)

Please swap them as follows:

-    logger_manager.setup_logfile(workdir=workdir)
+    logger_manager.setup(
+        handlers=log_handlers,
+        settings=self.output_settings,
+    )
+    logger_manager.setup_logfile(workdir=workdir)
-    logger_manager.setup(
-        handlers=log_handlers,
-        settings=self.output_settings,
-    )

This ensures the file handler isn’t cleared immediately after being added.

⛔ Skipped due to learnings
Learnt from: cademirch
PR: snakemake/snakemake#3107
File: snakemake/logging.py:806-830
Timestamp: 2024-09-30T17:17:37.360Z
Learning: In the Snakemake project's `Logger.handler` method, the mapping of the custom log level `'info'` to `_logging.WARNING` is intentional to preserve the existing log output coloring.
Learnt from: johanneskoester
PR: snakemake/snakemake#3600
File: src/snakemake/jobs.py:960-964
Timestamp: 2025-05-23T09:40:24.474Z
Learning: In the `cleanup` method of the `Job` class in `src/snakemake/jobs.py`, files in the `to_remove` list should be formatted with `fmt_iofile` without specifying `as_output=True` or `as_input=True` parameters, as these files should be displayed as generic files rather than specifically as output files.

Comment thread src/snakemake/logging.py
Comment thread src/snakemake/logging.py
@cademirch
Copy link
Copy Markdown
Contributor Author

Replaced the boolean log_errors_only flag with settings:

log_level_override: Allows setting any log level (not just ERROR)
skip_plugin_handlers: Controls whether to use plugin handlers/queue infrastructure (for remote execution)

This gives us better control over logging behavior based on execution mode:

Subprocess mode: Sets log level to ERROR (currently), skips file logging
Remote mode: Skips plugin handlers/queue for simpler logging
Main process: Full logging with plugins and all features

Eventually I'd like to clean up the output when a subprocess job fails as its quite verbose. But that is not very high priority.

Comment thread src/snakemake/settings/types.py
Copy link
Copy Markdown
Contributor

@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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/snakemake/api.py (1)

257-269: Always initialize the logger; keep_logger should only affect teardown

setup_logger currently returns early when output_settings.keep_logger is True, leaving logging unconfigured and causing missing logs. Initialize logger_manager unconditionally (or at least only skip when logger_manager is already configured).

Location: src/snakemake/api.py — def setup_logger (≈ lines 257–269)

  • Remove the early guard so logger_manager.setup(...) is called with handlers built from output_settings.log_handler_settings.
  • Ensure LoggerManager.setup is safe to call repeatedly: stop any existing QueueListener and close previous handlers before creating new ones, or make setup idempotent; alternatively perform a config-equality check and skip setup only when already configured.
♻️ Duplicate comments (1)
src/snakemake/api.py (1)

111-113: Preserve init chain: call super().post_init()

Keeps base invariants and future checks intact.

 def __post_init__(self):
-        self.setup_logger()
+        super().__post_init__()
+        self.setup_logger()
🧹 Nitpick comments (2)
src/snakemake/workflow.py (1)

1204-1206: LGTM with a tiny nit: early-return before defining helper

Functional change is sound. For a micro win, return early when the rulegraph isn’t needed to avoid defining simple_rulegraph() on every call.

 def log_rulegraph(self):
-        def simple_rulegraph():
+        if not logger_manager.needs_rulegraph:
+            return
+        def simple_rulegraph():
@@
-        if logger_manager.needs_rulegraph:
-            rulegraph = simple_rulegraph()
-            logger.info(None, extra=dict(event=LogEvent.RULEGRAPH, rulegraph=rulegraph))
+        rulegraph = simple_rulegraph()
+        logger.info(None, extra=dict(event=LogEvent.RULEGRAPH, rulegraph=rulegraph))
src/snakemake/api.py (1)

155-166: Avoid creating the workdir implicitly during logfile setup

setup_logfile(workdir=workdir) will os.makedirs() the full path (including a non-existent workdir) before WorkflowApi switches directories. Move logfile setup to after WorkflowApi has changed into the workdir; call without an explicit path so it’s created relative to the effective CWD.

-        logger_manager.setup_logfile(workdir=workdir)
         self._workflow_api = WorkflowApi(
             snakemake_api=self,
             snakefile=snakefile,
             workdir=workdir,
@@
             storage_provider_settings=storage_provider_settings,
         )
+        # now that WorkdirHandler has switched CWD, create the per-workdir logfile
+        logger_manager.setup_logfile()
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42fdc63 and 920ff28.

📒 Files selected for processing (5)
  • src/snakemake/api.py (4 hunks)
  • src/snakemake/cli.py (3 hunks)
  • src/snakemake/settings/types.py (1 hunks)
  • src/snakemake/workflow.py (1 hunks)
  • tests/tests.py (0 hunks)
💤 Files with no reviewable changes (1)
  • tests/tests.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/snakemake/cli.py
  • src/snakemake/settings/types.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit configuration file

**/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

Files:

  • src/snakemake/workflow.py
  • src/snakemake/api.py
🧬 Code graph analysis (1)
src/snakemake/api.py (2)
src/snakemake/logging.py (1)
  • setup_logfile (676-696)
src/snakemake/workflow.py (1)
  • workdir (1692-1696)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (55)
  • GitHub Check: tests (10, windows-2022, py313)
  • GitHub Check: tests (10, ubuntu-latest, py313)
  • GitHub Check: tests (10, ubuntu-latest, py312)
  • GitHub Check: tests (10, ubuntu-latest, py311)
  • GitHub Check: tests (10, windows-2022, py312)
  • GitHub Check: tests (9, ubuntu-latest, py313)
  • GitHub Check: tests (9, ubuntu-latest, py312)
  • GitHub Check: tests (9, windows-2022, py313)
  • GitHub Check: tests (9, windows-2022, py312)
  • GitHub Check: tests (9, macos-latest, py312)
  • GitHub Check: tests (8, windows-2022, py313)
  • GitHub Check: tests (4, windows-2022, py312)
  • GitHub Check: tests (8, ubuntu-latest, py311)
  • GitHub Check: tests (8, ubuntu-latest, py312)
  • GitHub Check: tests (8, ubuntu-latest, py313)
  • GitHub Check: tests (7, windows-2022, py312)
  • GitHub Check: tests (9, ubuntu-latest, py311)
  • GitHub Check: tests (7, ubuntu-latest, py311)
  • GitHub Check: tests (7, ubuntu-latest, py313)
  • GitHub Check: tests (8, windows-2022, py312)
  • GitHub Check: tests (7, windows-2022, py313)
  • GitHub Check: tests (7, macos-latest, py312)
  • GitHub Check: tests (6, windows-2022, py313)
  • GitHub Check: tests (6, ubuntu-latest, py311)
  • GitHub Check: tests (5, ubuntu-latest, py313)
  • GitHub Check: tests (6, windows-2022, py312)
  • GitHub Check: tests (7, ubuntu-latest, py312)
  • GitHub Check: tests (6, ubuntu-latest, py312)
  • GitHub Check: tests (5, windows-2022, py313)
  • GitHub Check: tests (4, windows-2022, py313)
  • GitHub Check: tests (6, ubuntu-latest, py313)
  • GitHub Check: tests (5, windows-2022, py312)
  • GitHub Check: tests (5, ubuntu-latest, py311)
  • GitHub Check: tests (3, windows-2022, py312)
  • GitHub Check: tests (3, windows-2022, py313)
  • GitHub Check: tests (5, ubuntu-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py311)
  • GitHub Check: tests (3, macos-latest, py312)
  • GitHub Check: tests (4, ubuntu-latest, py313)
  • GitHub Check: tests (3, ubuntu-latest, py311)
  • GitHub Check: tests (3, ubuntu-latest, py313)
  • GitHub Check: tests (3, macos-latest, py313)
  • GitHub Check: tests (4, ubuntu-latest, py312)
  • GitHub Check: tests (3, ubuntu-latest, py312)
  • GitHub Check: tests (2, windows-2022, py313)
  • GitHub Check: tests (2, windows-2022, py312)
  • GitHub Check: tests (2, ubuntu-latest, py313)
  • GitHub Check: tests (2, ubuntu-latest, py311)
  • GitHub Check: tests (1, ubuntu-latest, py312)
  • GitHub Check: tests (1, ubuntu-latest, py311)
  • GitHub Check: tests (1, windows-2022, py313)
  • GitHub Check: tests (2, ubuntu-latest, py312)
  • GitHub Check: tests (1, macos-latest, py312)
  • GitHub Check: tests (1, ubuntu-latest, py313)
  • GitHub Check: tests (1, windows-2022, py312)

@cademirch cademirch merged commit 47ae16e into snakemake:main Sep 15, 2025
80 checks passed
johanneskoester pushed a commit that referenced this pull request Sep 18, 2025
🤖 I have created a release *beep* *boop*
---


##
[9.11.3](v9.11.2...v9.11.3)
(2025-09-16)


### Bug Fixes

* logging refinements
([#3571](#3571))
([47ae16e](47ae16e))
* use proper default and fallback LP solver in scheduler settings
(thanks [@raffienficiaud](https://github.com/raffienficiaud))
([#3736](#3736))
([e00e5aa](e00e5aa))


### Documentation

* mention nodefaults for installation
([a6db049](a6db049))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
kjohnsen pushed a commit to kjohnsen/snakemake that referenced this pull request Dec 15, 2025
This PR refines some of the changes from the logging refactor to tackle
some issues as well as simplify the code.

Changes:
## `ExecMode` added to `OutputSettings`:
- ExecMode is critical to setting up the logger and controls how logs
are written, so from this perspective I think it makes sense that
ExecMode fits here
- Moving ExecMode here allows the logger to be setup in SnakemakeAPI,
which has multiple positive effects: the logger only needs to be setup
once in all of Snakemake's lifecycle, the logger is setup before the
workflow, allowing for workflow files to use the logger (snakemake#3558), and the
logger does not need to manage state anymore.
- This could be seen as a breaking change, though I've set the default
for this field to be ExecMode.DEFAULT so existing callers would be
unaffected.

## Setup logger no longer dependent on
`executor_plugin.common_settings.dryrun_exec`
- Another reason the logger had to be setup late in the Snakemake
lifecycle was that the stdout setting was dependent on this executor
plugin setting
- During refactoring I didn't question this, but now after looking at
most of the executor plugins, I haven't seen any that use this, so I'm
not sure the rationale behind tying stdout to this. @johanneskoester do
you happen to know?

## QueueHandler only used for plugins
- Only spin up queue overhead for logger plugins if they are being used.

## Added more tests
- Added test for specifiyng logger in Snakefile

### QC
<!-- Make sure that you can tick the boxes below. -->

* [ ] The PR contains a test case for the changes or the changes are
already covered by an existing test case.
* [ ] The documentation (`docs/`) is updated to reflect the changes or
this is not necessary (e.g. if the change does neither modify the
language nor the behavior or functionalities of Snakemake).


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added configurable output settings to control log level overrides,
plugin handler usage, and file logging.
* Added comprehensive logging tests and supporting test workflows to
validate logging behavior and failure scenarios.

* **Bug Fixes**
* Centralized and stabilized logger initialization for more consistent
logging across runs.

* **Refactor**
* Simplified logging setup by removing mode-based branching and
consolidating output-settings creation and handler management.

* **Documentation**
  * Documented the logging module and centralized logger management.

* **Chores**
  * Removed an outdated logfile test and updated test coverage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Johannes Köster <[email protected]>
kjohnsen pushed a commit to kjohnsen/snakemake that referenced this pull request Dec 15, 2025
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.

2 participants