Pytest: Feature request: use caplog with custom formatter

Created on 30 Nov 2017  路  6Comments  路  Source: pytest-dev/pytest

My application uses a quite heavily customized logging formatter.
Right now, the logging plugin only allows to specify the formats for the formatter, not completely replacing it.
It would be nice if there was a clean way to provide a custom formatter.

This is the workaround I use for now, patching the plugin class on the module:

from _pytest import logging as pytest_logging

def pytest_configure(config):
    config.pluginmanager.get_plugin('logging').LoggingPlugin = MyLoggingPlugin

class MyLoggingPlugin(pytest_logging.LoggingPlugin):
    def __init__(self, config):
        super().__init__(config)
        self.formatter = MyCustomFormatter()
logging proposal

All 6 comments

Perhaps this can be implemented as a hook:

@hookimpl(firstresult=True)
def pytest_logging_formatter(config):
    """Return a logging.Formatter instance that will be used by the internal logging capture"""

Then you can do this in your root conftest.py file:

def pytest_logging_formatter(config):
    return MyCustomFormatter()

as with other topics, i'd like to point to the fact that pytest hooks are a poor mechanism for selecting a "driver"

an ini option/section to select a formatter object and/or its parameters would be nice

Closing this issue as the proposal has been inactive for over a year.

I think this should be reopened. It is needed for #4485.

Expanding on @nicoulaj's solution, I recommend patching the _create_formatter method to replace the formatter for both caplog and live logging

class StructlogLoggingPlugin(pytest_logging.LoggingPlugin):
    """Replacement logging plugin that uses our formatter
    """
    def _create_formatter(self, log_format,
                          log_date_format) -> logging.Formatter:
        """Patch the logger method to always return out formatter
        Returns:
            logging.Formatter: Our structlog enhanced formatter
        """
        del log_format, log_date_format
        return <your formatter>

One option (definitely not optimal) would be to instantiate your custom formatter and set it explicitly on the caplog handler.

def test_my_function(caplog)
    formatter = MyCustomFormatter()
    caplog.handler.setFormatter(formatter)

    my_function()
    assert caplog.text == ....
Was this page helpful?
0 / 5 - 0 ratings