8

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

3 Answers 3

14

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
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for posting the example, just curious to know , why it's not working with setLevel as INFO ,i i.e ch.setLevel(logging.INFO) & logger.info("Message")
Thanks again, one last thing I am trying to do is, if I edit like this then my default logging message doesn't works, i.e logger.info("This is my sample log") gives me AttributeError : 'tuple' object has no attribute 'get'
0

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

Comments

-1

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')

1 Comment

By meaning of custom message it means it will contain diffrent values each time , Hence this is not a correct answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.