six8 / logaware

Python Logger that is context aware
BSD 2-Clause "Simplified" License
2 stars 2 forks source link

Getting the logger for modules #4

Closed symbolix closed 8 years ago

symbolix commented 8 years ago

Hi,

I have been doing a bit of testing and I think I am getting pretty comfortable with the API of logaware. The examples and our discussions in the previous issues was really helpful. Thank you very much for that.

Right now, I am trying to minimise the boiler plate stuff required to get the logger working across an application and any modules. It is already very efficient and it seems like it is all working very well.

So this is what I have in my main app:

#myApp.py
# Native logging.
import logging

# logaware specific imports.
from logaware.logger import AwareLogger, LogFormatException, LogLevel, log_method_factory
from logaware.metalogger import LogMetaManager, MetaAwareLogger

# logaware extension specific to this project.
from logger import ContextLogFormatter

# First configure top-level logger using the native logging.
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# Initialize the meta logger.
meta = LogMetaManager()

# Assign a context to the logger. This should be 'vim' if we are running inside vim or
# simply 'cli' if we are running as a command line.
meta.set_meta(context='cli')

# Initialize the MetaAwareLogger.
log = MetaAwareLogger(lambda: meta.get_meta())

# From here on, it is all the usual logging procedures (handlers, formatters etc.)
(...)

The question is, in a module that is also required to use the same logger, do we need to do anything special? For example, this is how I have things set-up in a module:

# entity.py - which is a module of myApp.py
# Initial imports
import logging

# logaware specific imports.
from logaware.logger import AwareLogger, LogFormatException, LogLevel, log_method_factory
from logaware.metalogger import LogMetaManager, MetaAwareLogger

# Introduce the logaware meta logger.
meta = LogMetaManager()
meta.set_meta(context='cli')

 #Assign an initial context.
log = MetaAwareLogger(lambda: meta.get_meta())

# From here on, it is only log messages.
(...)

And I am getting this:

[2016-11-04 16:59:58,818] [context=cli] <myApp:<module>:43> DEBUG: Hello World!
[2016-11-04 16:59:58,819] [context=cli] <myApp:<module>:49> DEBUG: Is this a debug message?
[2016-11-04 16:59:58,820] [context=cli] <entity:__init__:30> DEBUG: Class instance call.
[2016-11-04 16:59:58,820] [context=cli] <entity:get_name:38> INFO: PET name is Molly
[2016-11-04 16:59:58,820] [context=cli] <entity:third_party:43> INFO: Initial message from: _THIRD_PARTY!
[2016-11-04 16:59:58,820] [context=cli] <entity:another_function:48> WARNING: Message from: _ANOTHER_FUNCTION
[2016-11-04 16:59:58,821] [context=cli] <myApp:cmd:62> WARNING: Hello from __CMD!
[2016-11-04 16:59:58,821] [context=cli] <myApp:foo:58> DEBUG: Hello from __FOO?
[2016-11-04 16:59:58,821] [context=cli] <myApp:foo:59> INFO: Also inside __FOO?

Which is really working well for me. So usually, with the native logging it would be something like:

log = logging.getLogger('main')

at the start of the main application and then in the module:

log=logging.getLogger('main.entity')

and the logging will be simply connecting to the same logger. It seems like we do not need that with the logaware module? How much of the initial logaware boiler plate code do I need at the start of a module?

Thanks.

symbolix commented 8 years ago

I also wrote a simple formatter that works together with logaware, so that I can change the look of how the contextual information is displayed:

class ContextLogFormatter(logging.Formatter):
    """
    Flattens the contextual information into a string that later can be mapped
    to the %(context)s slot assigned by the format string.
    """
    def format(self, record):
        if record.meta:
            if 'context' in record.meta:
                record.context = '{}={}'.format('context', record.meta.get('context', None))
            else:
                record.context = 'context=None'

        # Return the result.
        return super(ContextLogFormatter, self).format(record)

Then I just attach that as a normal formatter. And it works. I hope that is how I should be doing this. Thanks.

symbolix commented 8 years ago

Do not worry about this issue. I can see that logaware is taking care of this when internally requesting the logger.

six8 commented 8 years ago

Yep. You can just always import log and use it from log = MetaAwareLogger(lambda: meta.get_meta()). That's part of the purpose of logaware -- never having to use a module specific logger.