coder3521
coder3521

Reputation: 2646

Logging with multiple parameters in python

In python logging module Log is formatted using below :

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

**simple_example.py**
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')

Which gives output as below :

OUTPUT:

2005-03-19 15:10:26,618 - simple_example - DEBUG - debug message
2005-03-19 15:10:26,620 - simple_example - INFO - info message
2005-03-19 15:10:26,695 - simple_example - WARNING - warn message

I am just wondering if there is any way to add multiple messages not at the end but in between i.e something like

 My custom message 1  - simple_example - DEBUG - my custom message 2

Is there any way I could format it like:

formatter = logging.Formatter('%(message1)s - %(name)s - %(levelname)s - %(message2)s')

Any help would be appreciated

Upvotes: 8

Views: 29166

Answers (3)

user16776498
user16776498

Reputation:

You can create your logger class and decorate your methods with this:

@staticmethod
def combine(func):
    def wrapped(self, *args, **kwargs):
        for i,v in enumerate(args):
            if v:
                func(self,f"\n {chr(i+65)} : {v}",**kwargs)
 
    return wrapped

example:

import logging


class my_log():
    def __init__(self, name, debug=True):
        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging.DEBUG)
        formatter = logging.Formatter("%(asctime)s;%(levelname)s;%(message)s",
                                      "%Y-%m-%d %H:%M:%S")
        path = 'log.txt'
        try:
            fh = logging.FileHandler(path, 'a')
        except FileNotFoundError:
            fh = logging.FileHandler(path, 'w')
        fh.setFormatter(formatter)
        fh.setLevel(logging.DEBUG)
        self.logger.addHandler(fh)
        if debug:
            # create console handler and set level to debug
            ch = logging.StreamHandler()
            ch.setLevel(logging.DEBUG)
            # add formatter to ch
            ch.setFormatter(formatter)
            # add ch to logger
            self.logger.addHandler(ch)
            self.logger.removeHandler(fh)

    @staticmethod
    def combine(func):
        def wrapped(self, *args, **kwargs):
            for i, v in enumerate(args):
                if v:
                    func(self, f"\n {chr(i+65)} : {v}", **kwargs)

        return wrapped

    def get_logger(self) -> logging.Logger:
        return self.logger

    @combine
    def debug(self, string: str):
        self.logger.debug(string)


l = my_log("test")
l.debug(1, 2, 3, 4)

output:

2022-01-24 21:23:59;DEBUG;
 A : 1
2022-01-24 21:23:59;DEBUG;
 B : 2
2022-01-24 21:23:59;DEBUG;
 C : 3
2022-01-24 21:23:59;DEBUG;
 D : 4

Upvotes: 0

Mike Scotty
Mike Scotty

Reputation: 10782

You could write your own Formatter class and pass your extra message as kwargs:

import logging

class MyFormatter(logging.Formatter):
    def format(self, record):
        record.message2 = record.args.get("message2")
        return super().format(record)

logger = logging.getLogger('test')
ch = logging.StreamHandler()
formatter = MyFormatter('%(asctime)s - %(message2)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
ch.setLevel(logging.ERROR)
logger.addHandler(ch)

logger.error("debug message", {"message2": "Blub"})

Output:

2019-02-08 14:33:50,487 - Blub - test - ERROR - debug message


Edit: I do not know, why this does not work out-of-the-box with INFO level, but you could do the following, which will work:

import logging

class MyFormatter(logging.Formatter):
    def format(self, record):
        record.message2 = record.args.get("message2")
        return super().format(record)

logger = logging.getLogger('test')
ch = logging.StreamHandler()
ch.setFormatter(MyFormatter('%(asctime)s - %(message2)s - %(name)s - %(levelname)s - %(message)s'))
logging.basicConfig( level=logging.INFO, handlers=[ch] )

logger.info("debug message", {"message2": "Blub"})

Output:

2019-02-11 12:53:17,014 - Blub - test - INFO - debug message


Edit 2: For this to work w/o providing a dict with message2, you can change the code as follows:

import logging

class MyFormatter(logging.Formatter):
    def format(self, record):
        record.message2 = ""
        if(record.args):
            record.message2 = record.args.get("message2", "Fallback Value")
        return super().format(record)

logger = logging.getLogger('test')
ch = logging.StreamHandler()
ch.setFormatter(MyFormatter('%(asctime)s - %(message2)s - %(name)s - %(levelname)s - %(message)s'))
logging.basicConfig( level=logging.INFO, handlers=[ch] )

logger.info("debug message", {"message2": "Blub"})
logger.info("This is my sample log")
logger.info("This is my sample log", {"hello": "World"})

Output:

2019-02-11 13:20:53,419 - Blub - test - INFO - debug message
2019-02-11 13:20:53,419 -  - test - INFO - This is my sample log
2019-02-11 13:20:53,419 - Fallback Value - test - INFO - This is my sample log

Upvotes: 13

Amit Nanaware
Amit Nanaware

Reputation: 3346

Hi you can use your custom message directly in Formatter and use %(message)s to place your logging message

See below example

formatter = logging.Formatter('My custome message 1 - %(name)s - %(levelname)s - %(message)s my custom message 2')

Upvotes: -1

Related Questions