#!/usr/bin/env python #-*- encoding: gbk -*- # import ConfigParser import logging import time, os from logging.handlers import RotatingFileHandler import platform #global log_msg_root = '_msg_log_' #log_stderr_format = '$RESET$COLOR<%(levelname)-5s><%(name)s:%(process)d:%(threadName)s><%(filename)s:%(lineno)d>%(message)s' log_stderr_format = '$COLOR$BOLD<%(levelname)-5s><%(name)s:%(process)d:%(threadName)s>$RESET$COLOR<%(filename)s:%(lineno)d>%(message)s' #log_stderr_format = "$COLOR%(levelname)s $RESET %(asctime)s $BOLD$COLOR%(name)s$RESET %(message)s" if platform.system() == 'Windows': log_file_format = '<%(levelname)s><%(name)s:%(process)d>%(message)s' else: log_file_format = '%(asctime)s <%(levelname)-5s><%(name)s:%(process)d:%(threadName)s><%(filename)s:%(lineno)d>%(message)s' # for colorful stderr output, copy from http://stackoverflow.com/questions/384076/how-can-i-make-the-python-logging-output-to-be-colored # by rrt BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) RESET_SEQ = "\033[0m" #COLOR_SEQ = "\033[1;%dm" # color & bold COLOR_SEQ = "\033[0;%dm" # color only BOLD_SEQ = "\033[1m" COLORS={ 'WARNING':WHITE, 'INFO':YELLOW, 'DEBUG':GREEN, 'CRITICAL':YELLOW, 'ERROR':RED, 'RED':RED, 'GREEN':GREEN, 'YELLOW':YELLOW, 'BLUE':BLUE, 'MAGENTA':MAGENTA, 'CYAN':CYAN, 'WHITE':WHITE,} """ COLORS = { 'INFO': YELLOW, 'DEBUG': GREEN, 'ERROR': RED } """ class ColoredFormatter(logging.Formatter): def __init__(self, *args, **kwargs): logging.Formatter.__init__(self, *args, **kwargs) def format(self, record): levelname = record.levelname color = COLOR_SEQ % (30 + COLORS[levelname]) message = logging.Formatter.format(self, record) #print "1--" + repr(message) message = message.replace("$RESET", RESET_SEQ)\ .replace("$BOLD", BOLD_SEQ)\ .replace("$COLOR", color) #print "2--" + repr(message) #for k,v in COLORS.items(): # message = message.replace("$" + k, COLOR_SEQ % (v+30))\ # .replace("$BG" + k, COLOR_SEQ % (v+40))\ # .replace("$BG-" + k, COLOR_SEQ % (v+40)) #print "3--" + repr(message) return message + RESET_SEQ #This class copy form liup's blog http://hi.baidu.com/dalier/blog/item/68419d64b98604faf63654e4.html #by rrt on 2010-12-3 class DateRotatingFileHandler(RotatingFileHandler): def __init__(self , filename , mode='a' , maxBytes=0, backupCount=0, encoding=None): self.current = time.strftime("%Y%m%d" , time.localtime(time.time())) self.path = os.path.dirname(filename) self.filename = os.path.basename(filename) newdir = os.path.join(self.path , self.current) softlink = os.path.join(self.path, 'current') if not os.access(newdir , os.X_OK): os.mkdir(newdir) try: os.symlink(newdir ,softlink) except: os.system("rm -f " + softlink) os.symlink(newdir ,softlink) newfile = os.path.join(newdir , self.filename) RotatingFileHandler.__init__(self, newfile , mode, maxBytes , backupCount , encoding) def doRollover(self): #print "doRollover , current=%s , filename=%s"%(self.current , self.baseFilename) self.stream.close() self.current = time.strftime("%Y%m%d" , time.localtime(time.time())) #Modified by rrt on 2010-12-4 for a log path bug: /'20101204' #repr() is not needed , time.strftime() return a string not a integer #newdir = os.path.join(self.path , repr(self.current)) newdir = os.path.join(self.path , self.current) if not os.access(newdir , os.X_OK): os.mkdir(newdir) self.baseFilename = os.path.join(newdir , self.filename) if self.encoding: self.stream = codecs.open(self.baseFilename, 'w', self.encoding) else: self.stream = open(self.baseFilename, 'w') def shouldRollover(self, record): if RotatingFileHandler.shouldRollover(self , record): RotatingFileHandler.doRollover(self) t = time.strftime("%Y%m%d" , time.localtime(time.time())) if (cmp(self.current , t) < 0) : return 1 return 0 def init_log(prefix, cfg_file, type,level): global log_msg_root, log_file_format, log_stderr_format cf = ConfigParser.ConfigParser() cf.read(cfg_file) config = {} # we can use # = cf.get(prefix, 'level').split('#')[0].strip() # to enable "#" to comment behind a value string. try: config['level'] = cf.get(prefix, 'level') except: config['level'] = cf.get(log_msg_root, 'level') try: config['file'] = cf.get(prefix, 'file') except: path = cf.get(log_msg_root, 'file') path = os.path.dirname(path) config['file'] = os.path.join(path, prefix+'.log') try: config['stderr'] = cf.getint(prefix, 'stderr') except: config['stderr'] = cf.getint(log_msg_root, 'stderr') try: config['syslog'] = cf.getint(prefix, 'syslog') except: config['syslog'] = cf.getint(log_msg_root, 'syslog') try: config['file_size'] = cf.getint(prefix, 'file_size') except: config['file_size'] = cf.getint(log_msg_root, 'file_size') try: config['file_cnt'] = cf.getint(prefix, 'file_counter') except: config['file_cnt'] = cf.getint(log_msg_root, 'file_counter') print config #new a root logger logger = logging.getLogger(prefix) #set root logger level if config['level'] == 'debug': logger.setLevel(logging.DEBUG) elif config['level'] == 'info': logger.setLevel(logging.INFO) else: logger.setLevel(logging.ERROR) #new a log file handle log_handler = DateRotatingFileHandler(config['file'], mode="a", maxBytes = config['file_size']*1024*1024, backupCount=config['file_cnt']) #set log file handle format formatter = logging.Formatter(log_file_format, datefmt='%Y-%m-%d %H:%M:%S')# '%F %T') jython not work log_handler.setFormatter(formatter) #add to root logger logger.addHandler(log_handler) #new a stderr logger if need if not config['stderr']: return logger else: formatter = ColoredFormatter(log_stderr_format) #formatter = logging.Formatter(log_stderr_format) log_handler = logging.StreamHandler() log_handler.setFormatter(formatter) logger.addHandler(log_handler) return logger if __name__ == '__main__': global logger logger = init_log('test_log_lib', 'msg_log.ini', 0, 0) logger.debug('debug rrrrrrrrrrrrrrrrrrrrrrrrrrrt') logger.info('info rrrrrrrrrrrrrrrrrrrrrrrrrrrt') logger.error('error rrrrrrrrrrrrrrrrrrrrrrrrrrrt')