Snakemake Logger Plugin Interface

2.0.1 · active · verified Thu Apr 16

The `snakemake-interface-logger-plugins` library provides the abstract base classes and registry for implementing custom logger plugins for Snakemake. It defines the interface for `LoggerPlugin` and `LoggerWrapper` classes, allowing users to extend Snakemake's logging capabilities. The current version is 2.0.1 and it follows the Snakemake plugin API's release cadence, typically tied to major Snakemake versions.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to create a basic Snakemake logger plugin. It defines `MyLoggerPlugin` (the entry point for Snakemake) and `MyLoggerWrapper` (which handles the actual logging messages). It also shows how to register custom command-line arguments and access them via settings. To use, save the code as `my_custom_logger.py` and run Snakemake with `--logger-plugin my_custom_logger.py`.

import os
from argparse import ArgumentParser
from snakemake_interface_logger_plugins.plugin import LoggerPlugin
from snakemake_interface_logger_plugins.wrapper import LoggerWrapper
from snakemake_interface_logger_plugins.settings import CommonLoggerSettings

# Save this as my_custom_logger.py

class MyLoggerPlugin(LoggerPlugin):
    """A simple custom logger plugin for Snakemake."""
    def __init__(self, settings: CommonLoggerSettings | None = None):
        self.settings = settings

    def register_args(self, argparser: ArgumentParser):
        """Register command line arguments for this plugin."""
        argparser.add_argument(
            "--my-logger-prefix",
            default="[CUSTOM LOG]",
            help="Prefix for custom logger messages."
        )

    def setup(self):
        """Perform setup actions before any logging occurs."""
        # Access custom args via self.settings if defined
        # print(f"{self.settings.my_logger_prefix} Initializing MyLoggerPlugin...")
        pass # For this minimal example, we don't need complex setup

    def get_wrapper(self) -> LoggerWrapper:
        """Return an instance of the logger wrapper."""
        return MyLoggerWrapper(self.settings)

class MyLoggerWrapper(LoggerWrapper):
    """Handles actual logging events."""
    def __init__(self, settings: CommonLoggerSettings | None = None):
        self.settings = settings

    def handle_info(self, msg: str):
        prefix = getattr(self.settings, 'my_logger_prefix', '[MYLOGGER]')
        print(f"{prefix} INFO: {msg}")

    def handle_error(self, msg: str):
        prefix = getattr(self.settings, 'my_logger_prefix', '[MYLOGGER]')
        print(f"{prefix} ERROR: {msg}")

    # Implement other handle_* methods as needed for full functionality
    # e.g., handle_log, handle_job_info, handle_job_error, handle_start, handle_finish, etc.
    # For this example, we only show info and error.
    # All abstract methods must be implemented, even if with a 'pass'
    def handle_log(self, msg: str):
        prefix = getattr(self.settings, 'my_logger_prefix', '[MYLOGGER]')
        print(f"{prefix} LOG: {msg}")

    def handle_start(self):
        prefix = getattr(self.settings, 'my_logger_prefix', '[MYLOGGER]')
        print(f"{prefix} Workflow started.")

    def handle_finish(self):
        prefix = getattr(self.settings, 'my_logger_prefix', '[MYLOGGER]')
        print(f"{prefix} Workflow finished.")

    def handle_job_info(self, job_info: dict):
        prefix = getattr(self.settings, 'my_logger_prefix', '[MYLOGGER]')
        print(f"{prefix} Job info: {job_info.get('jobid')} - {job_info.get('output')}")

    def handle_job_error(self, job_info: dict):
        prefix = getattr(self.settings, 'my_logger_prefix', '[MYLOGGER]')
        print(f"{prefix} Job error: {job_info.get('jobid')} - {job_info.get('output')}")

# To run this with Snakemake, save it as `my_custom_logger.py` and then run:
# snakemake --snakefile Snakefile --logger-plugin my_custom_logger.py --my-logger-prefix "[SNAKEMAKE-CUSTOM]" -c1
# (Requires a simple Snakefile, e.g., 'rule all: run: print("Hello from Snakemake")')

view raw JSON →