Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant way to make logging.LoggerAdapter available to other modules

I use a LoggerAdapter to let my python logging output Linux TIDs instead of the long unique IDs. But this way I don't modify an existing logger but I create a new object:

    new_logger = logging.LoggerAdapter(
                    logger=logging.getLogger('mylogger'), 
                    extra=my_tid_extractor())

Now I want this LoggerAdapter be used by certain modules. As long as I know a global variable being used as logger I can do something like this:

    somemodule.logger = new_logger

But this is not nice - it works only in a couple of cases and you need to know the logger variables used by the modules.

Do you know a way to make a LoggerAdapter available globally e.g. by calling s.th. like

    logging.setLogger('mylogger', new_logger)

Or alternatively: is there some other way to let Python logging output Linux thread IDs like printed by ps?

like image 637
frans Avatar asked Jan 20 '15 16:01

frans


People also ask

How do you show logging information in Python?

Python Logging – INFO Level To log an INFO line using Python Logging, Check if the logger has atleast a logging level of INFO. Use logging.info() method, with the message passed as argument, to print the INFO line to the console or log file.

How do I create a multiple logging level in Python?

You can set a different logging level for each logging handler but it seems you will have to set the logger's level to the "lowest". In the example below I set the logger to DEBUG, the stream handler to INFO and the TimedRotatingFileHandler to DEBUG. So the file has DEBUG entries and the stream outputs only INFO.


2 Answers

Alternatively, you can to implement custom logger, and make it default in logging module.

Here is example:

import logging
import ctypes

SYS_gettid = 186
libc = ctypes.cdll.LoadLibrary('libc.so.6')

FORMAT = '%(asctime)-15s [thread=%(tid)s] %(message)s'
logging.basicConfig(level=logging.DEBUG, format=FORMAT)

def my_tid_extractor():
    tid = libc.syscall(SYS_gettid)
    return {'tid': tid}

class CustomLogger(logging.Logger):

    def _log(self, level, msg, args, exc_info=None, extra=None):
        if extra is None:
            extra = my_tid_extractor()
        super(CustomLogger, self)._log(level, msg, args, exc_info, extra)

logging.setLoggerClass(CustomLogger)


logger = logging.getLogger('test')
logger.debug('test')

Output sample:

2015-01-20 19:24:09,782 [thread=5017] test
like image 162
Dmitry Nedbaylo Avatar answered Oct 24 '22 09:10

Dmitry Nedbaylo


I think you need override LoggerAdapter.process() method Because the default LoggerAdapter.process method will do nothing, Here is example:

import logging
import random
L=logging.getLogger('name')

class myLogger(logging.LoggerAdapter):
    def process(self,msg,kwargs):
        return '(%d),%s' % (self.extra['name1'](1,1000),msg)  ,kwargs

#put the randint function object  
LA=myLogger(L,{'name1':random.randint})

#now,do some logging
LA.debug('some_loging_messsage')

out>>DEBUG:name:(167),some_loging_messsage 
like image 28
hm_go1988 Avatar answered Oct 24 '22 09:10

hm_go1988