Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: use caplog with custom formatter #2987

Open
nicoulaj opened this issue Nov 30, 2017 · 9 comments
Open

Feature request: use caplog with custom formatter #2987

nicoulaj opened this issue Nov 30, 2017 · 9 comments
Labels
plugin: logging related to the logging builtin plugin type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature

Comments

@nicoulaj
Copy link

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()
@nicoddemus nicoddemus added plugin: logging related to the logging builtin plugin type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature labels Nov 30, 2017
@nicoddemus
Copy link
Member

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()

@RonnyPfannschmidt
Copy link
Member

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

@Zac-HD
Copy link
Member

Zac-HD commented Feb 25, 2019

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

@Zac-HD Zac-HD closed this as completed Feb 25, 2019
@twmr
Copy link
Contributor

twmr commented Feb 25, 2019

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

@samvasko
Copy link

samvasko commented Oct 11, 2019

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>

@brechin
Copy link

brechin commented Jun 29, 2020

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 == ....

@Emantor
Copy link

Emantor commented Oct 20, 2022

Simply replacing the formatter by retrieving the logging plugin also works.

logging = config.pluginmanager.getplugin('logging-plugin')
logging.log_cli_handler.setFormatter(YourCustomFormatter())
logging.log_file_handler.setFormatter(YourCustomFormatter())

There is only ever one formatter attached to handler, so you are effectively replacing the existing one.

@soxofaan
Copy link
Contributor

soxofaan commented Mar 8, 2023

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)

I've used this pattern, but just got bitten by an undesired side-effect: subsequent tests that also use caplog will also get the custom formatter because the original formatter is not automatically restored on tear down.

A slightly improved version that does take care of restoring the original formatter is as follows:

def test_my_function(caplog, monkeypatch)
    monkeypatch.setattr(caplog.handler, "formatter", MyCustomFormatter())

    my_function()
    assert caplog.text == ....

soxofaan added a commit to Open-EO/openeo-python-driver that referenced this issue Mar 8, 2023
soxofaan added a commit to Open-EO/openeo-geopyspark-driver that referenced this issue Mar 8, 2023
@jenstroeger
Copy link
Contributor

jenstroeger commented Nov 20, 2023

Maybe somewhat related to issue #11610 where we use a context manager to (temporarily) add a filter to the fixture…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: logging related to the logging builtin plugin type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature
Projects
None yet
Development

No branches or pull requests

10 participants