Describe per-package verbosity.

Each definitions item should be an iterable which describes the progression of log level at each level of verbosity.


This states that: urllib3 should start at INFO logs by default, then only increase to DEBUG at 3 verbosity (i.e. -vvv). And that sqlalchemy should start at WARNING, then INFO (at -v), and DEBUG (at -vv, -vvv, etc)

>>> package_verbosity = package_verbosity_factory(
...     ("urllib3", logging.INFO, logging.INFO, logging.INFO, logging.DEBUG),
...     ("sqlalchemy", logging.WARNING, logging.INFO, logging.DEBUG),
... )
>>> package_verbosity(0)
{'urllib3': 20, 'sqlalchemy': 30}
>>> package_verbosity(1)
{'urllib3': 20, 'sqlalchemy': 20}
>>> package_verbosity(2)
{'urllib3': 20, 'sqlalchemy': 10}
>>> package_verbosity(3)
{'urllib3': 10, 'sqlalchemy': 10}

Omitting the log level progression entirely isn’t really an intended usecase, but the returned callable accepts a default arg, which can be used to control the behavior in this case. It defaults to logging.INFO

>>> package_verbosity = package_verbosity_factory(["urllib3"])
>>> package_verbosity(0)
{'urllib3': 20}
>>> package_verbosity(0, default=logging.DEBUG)
{'urllib3': 10}

A callable which, given the desired verbosity, returns a mapping of package to log level.

This is most useful when paired with setuplog or loguru.

  • Setuplog’s setup_logging() accepts a log_level_overrides argument who’s format matches the output of this function.

  • Loguru’s loguru.add() function accepts a filter argument which who’s format is compatible with the output of this function.

For use in applications, it’s generally useful to call this as early as it is possible to have the level of verbosity you want.

For cli applications, this will tend to be inside the root cli group, where you accept the verbosity level.

import logging
import strapp.logging
from setuplog import setup_logging

package_verbosity = strapp.logging.package_verbosity_factory(
    ("urllib3", logging.INFO, logging.INFO, logging.INFO, logging.DEBUG),
    ("sqlalchemy.engine", logging.WARNING, logging.WARNING, logging.INFO, logging.DEBUG),
    ("docker", logging.INFO, logging.INFO, logging.INFO, logging.DEBUG),

@click.option('--verbose', count=True, default=0)
def cli(verbose):
        config.logging.level, log_level_overrides=package_verbosity(verbose),

For flask apps, this tends to be even earlier, i.e. as soon as you load the config.