Simple extension of Python core logging that provides ‘thread-local-aware’ logger. The term ‘MDC’ is inspired from MDC concept in various Java logging libraries.
import logging
import threading
__author__ = 'hoang281283@gmail.com'
class MDCLocal(threading.local):
def __init__(self):
self.mdc_dict = {"request_id": ""}
def set_attribute(self, key, value):
self.mdc_dict[key] = value
def remove_attribute(self, key):
del self.mdc_dic[key]
def get_attribute(self, key):
return self.mdc_dict[key]
def get_mdc_map(self):
return self.mdc_dict
def clear(self):
[self.mdc_dict.update({k: ""}) for k in self.mdc_dict]
MDC_BASIC_FORMAT = '%(asctime)s - %(name)s %(levelname)s - [%(request_id)s] : %(message)s'
MDC_MAP = MDCLocal()
class MDCLogger(logging.Logger):
def __init__(self, deco_logger):
self.deco_logger = deco_logger
def setLevel(self, level):
self.deco_logger.setLevel(level)
def debug(self, msg, *args, **kwargs):
self.deco_logger.debug(msg, extra=MDC_MAP.get_mdc_map(), *args, **kwargs)
def info(self, msg, *args, **kwargs):
self.deco_logger.info(msg, extra=MDC_MAP.get_mdc_map(), *args, **kwargs)
def warning(self, msg, *args, **kwargs):
self.deco_logger.warning(msg, extra=MDC_MAP.get_mdc_map(), *args, **kwargs)
def warn(self, msg, *args, **kwargs):
self.deco_logger.warning(msg, extra=MDC_MAP.get_mdc_map(), *args, **kwargs)
def error(self, msg, *args, **kwargs):
self.deco_logger.error(msg, extra=MDC_MAP.get_mdc_map(), *args, **kwargs)
def exception(self, msg, *args, **kwargs):
self.deco_logger.exception(msg, extra=MDC_MAP.get_mdc_map(), *args, **kwargs)
def critical(self, msg, *args, **kwargs):
self.deco_logger.critical(msg, extra=MDC_MAP.get_mdc_map(), *args, **kwargs)
def log(self, level, msg, *args, **kwargs):
self.deco_logger.critical(level, msg, extra=MDC_MAP.get_mdc_map(), *args, **kwargs)
def put_mdc(key, value):
MDC_MAP.set_attribute(key, value)
def clear_mdc():
MDC_MAP.clear()
def basic_config(**kwargs):
if 'format' in kwargs.keys():
pass
else:
kwargs['format'] = MDC_BASIC_FORMAT
logging.basicConfig(**kwargs)
def get_mdc_logger(name=None):
if name:
return MDCLogger(logging.getLogger(name))
else:
return MDCLogger(logging.root)
Code testing mdc_logging on multiple threads
import mdc_logging, logging, thread
mdc_logging.basic_config()
logger = mdc_logging.get_mdc_logger("SharedLogger")
def print_log_on_thread(s):
mdc_logging.put_mdc("request_id", s)
logger.warn("Blah blah")
mdc_logging.clear_mdc()
thread.start_new_thread(print_log_on_thread, (123456,))
thread.start_new_thread(print_log_on_thread, (654321,))









