Prefix log messages with context-dependent data

Viewed 42

I want to prefix all the log entries inside one class by self.instance_desc. Like this:

logging.info(f"({self.instance_desc}) {message}")

But I don't want to write the prefix in each message.

How can I make it so it's automatic?

Already done:

I've added a new method to the class:

def log(message):
    logging.info(f"({self.instance_desc}) Message")

The problem is that %(filename)s:%(lineno)d is (obviously) pointing to the log method.

Is it possible to do this while %(filename)s:%(lineno)d pointing to the place where the self.log has been called?

1 Answers

You can use the stacklevel keyword parameter to logging calls to make the adjustment. This script:

import logging

def custom_log(level, msg, *args, **kwargs):
    kwargs['stacklevel'] = 3
    # import pdb; pdb.set_trace()
    logging.log(level, 'prefix: ' + msg, *args, **kwargs)

def baz():
    custom_log(logging.DEBUG, 'baz')

def bar():
    custom_log(logging.DEBUG, 'bar')
    baz()

def foo():
    custom_log(logging.DEBUG, 'foo')
    bar()

logging.basicConfig(level=logging.DEBUG, format='line %(lineno)2d %(message)s')
foo()

should print

line 16 prefix: foo
line 12 prefix: bar
line  9 prefix: baz

In other words, it prints the location of the call to custom_log(). In my example it's a plain function rather than a method, but the principle's the same.

Related