markwalker_
markwalker_

Reputation: 12849

How to add logging to classes in a module at a custom level

I'm trying to replace an old method of logging information with standard Python logging to a file. The application currently has a log file which is set to capture Info and Debug messages so I would like this at a lower level that isn't captured by the main log.

App structure:

- mysite
- legacy
  -- items
     --- item1.py
  -- __init__.py
  -- engine.py

Within item1.py and engine.py are calls to an old debug() function which I'd not like to be logged in legacy.log but not have them appear in the mysite.log file.

Ideally the way this works is to create a wrapper with a debug function which does the logging at the new level and I've read that this requires an extension of logging.Logger.

So In legacy/__init__.py I've written;

import logging

LEGACY_DEBUG_LVL = 5

class LegacyLogger(logging.Logger):
    """
    Extend the Logger to introduce the new legacy logging.
    """
    def legacydebug(self, msg, *args, **kwargs):
        """
        Log messages from legacy provided they are strings.

        @param msg: message to log
        @type msg:
        """
        if isinstance(msg, str):
            self._log(LEGACY_DEBUG_LVL, msg, args)

    logging.Logger.legacydebug = legacydebug


logger = logging.getLogger('legacy')
logger.setLevel(LEGACY_DEBUG_LVL)
logger.addHandler(logging.FileHandler('legacy.log'))
logging.addLevelName(LEGACY_DEBUG_LVL, "legacydebug")

And from engine.py and item1.py I can just do;

from . import logger
debug = logger.legacydebug

At the moment I'm seeing messages logged to both logs. Is this the correct approach for what I want to achieve? I've got a talent for over-complicating things and missing the simple stuff!

edit

Logging in the main application settings is setup as such;

# settings.py
logging.captureWarnings(True)
logger = logging.getLogger()
logger.addHandler(logging.NullHandler())
logger.addHandler(logging.handlers.FileHandler('mysite.log'))

if DEBUG:
    # If we're running in debug mode, write logs to stdout as well:
    logger.addHandler(logging.StreamHandler())
    logger.setLevel(logging.DEBUG)
else:
    logger.setLevel(logging.INFO)

Upvotes: 1

Views: 362

Answers (1)

jorispilot
jorispilot

Reputation: 483

When using multiple loggers, the logging module implicitly creates them in a tree structure. The structure are defined by the logger name: a logger named 'animal' will be the parent of loggers called 'animal.cat' and 'animal.dog'.

In your case, the unnamed logger defined in settings.py is parent of the logger named 'legacy'. The unnamed logger will receive the messages sent through the 'legacy' logger, and write them into mysite.log.

Try to give a name for the unnamed logger, such as 'mysite' to break the tree structure.

Upvotes: 1

Related Questions