Skip to content

Logger names are not intuitive #1009

@llucax

Description

@llucax

What's needed?

We sometimes want to configure some loggers differently (for example to print debug messages), but it is not easy at all to figure out which logger should be configured when some high-level module is composed of other private modules that the user is never supposed to import directly, and __name__ is used as logger name, which maps to the fully qualified module name.

For example, the timeseries module have these debug log messages:

src/frequenz/sdk/timeseries/_grid_frequency.py:        _logger.debug("Sent request for grid frequency: %s", self._source_component)
src/frequenz/sdk/timeseries/_moving_window.py:            _logger.debug("Returning value at index %s ", key)
src/frequenz/sdk/timeseries/_moving_window.py:                _logger.debug("Received new sample: %s", sample)
src/frequenz/sdk/timeseries/_periodic_feature_extractor.py:        _logger.debug("Initializing PeriodicFeatureExtractor!")

If someone configures the logger frequenz.sdk.timeseries to print debug logs, they won't actually see any logs.
In these cases, the users have basically no reliable way to know which loggers they should configure.

Proposed solution

Option 1

Use always the high-level module name as logger name. We could use a convention, for example, to have a _logger.py module that instantiates and exposes the global logger for that high-level module, and then all the internal sub-modules will just import that logger.

To follow the example, we would have a src/frequenz/sdk/timeseries/_logger.py module like:

import logging

logger = logging.getLogger(__name__[:__name__.rindex('.')])

And then in, for example, src/frequenz/sdk/timeseries/_moving_window.py:

from ._logger import logger

# ...
            _logger.debug("Returning value at index %s ", key)

Option 2

Add some utility function to the SDK (or probably better core) to get the logger ignoring the private modules, like logger = get_public_logger(__name__):

import logging

def get_public_logger(module_name):
    parts = module_name.split('.')
    public_parts = []
    for part in parts:
        if part.startswith('_'):
            break
        public_parts.append(part)
    return logging.getLogger('.'.join(public_parts))

Metadata

Metadata

Assignees

No one assigned

    Labels

    part:coreAffects the SDK core components (data structures, etc.)resolution:invalidThis doesn't seem rightstatus:blockedOther issues must be resolved before this can be worked ontype:enhancementNew feature or enhancement visitble to users

    Type

    No type

    Projects

    Status

    Done

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions