# Written by Jie Yang # see LICENSE.txt for license information import sys import os import time import socket from traceback import print_exc from base64 import encodestring from sha import sha DEBUG = False log_separator = ' - ' logger = None # To be compatible with Logger from http://linux.duke.edu/projects/mini/logger/ # for 2fastbt (revision <=825). def create_logger(file_name): global logger logger = Logger(3, file_name) def get_logger(): global logger if logger is None: create_logger("global.log") return logger def get_today(): # UTC based return time.gmtime(time.time())[:3] class Logger: """ Atrributes (defulat value): threshold (): message will not be logged if its output_level is bigger than this threshould file_name (): log file name file_dir ('.'): diectory of log file. It can be absolute or relative path. prefix (''): prefix of log file prefix_date (False): if it is True, insert 'YYYYMMDD-' between prefix and file_name, e.g., sp-20060302-buddycast.log given prefix = 'sp-' and file_name = 'buddycast.log' open_mode ('a+b'): mode for open. """ def __init__(self, threshold, file_name, file_dir = '.', prefix = '', prefix_date = False, open_mode = 'a+b'): self.threshold = threshold if file_name == '': self.logfile = sys.stderr else: try: if not os.access(file_dir, os.F_OK): try: os.mkdir(file_dir) except os.error, msg: raise "logger: mkdir error: " + msg file_path = self.get_file_path(file_dir, prefix, prefix_date, file_name) self.logfile = open(file_path, open_mode) except Exception, msg: self.logfile = None print >> sys.stderr, "logger: cannot open log file", \ file_name, file_dir, prefix, prefix_date, msg print_exc() def __del__(self): self.close() def get_file_path(self, file_dir, prefix, prefix_date, file_name): if prefix_date is True: # create a new file for each day today = get_today() date = "%04d%02d%02d" % today else: date = '' return os.path.join(file_dir, prefix + date + file_name) def log(self, level, msg): if level <= self.threshold: if self.logfile is None: return time_stamp = "%.03f"%time.time() self.logfile.write(time_stamp + log_separator) if isinstance(msg, str): self.logfile.write(msg) else: self.logfile.write(repr(msg)) self.logfile.write('\n') self.logfile.flush() def close(self): if self.logfile is not None: self.logfile.close() class OverlayLogger: __single = None def __init__(self, file_name, file_dir = '.'): if OverlayLogger.__single: raise RuntimeError, "OverlayLogger is singleton" self.file_name = file_name self.file_dir = file_dir OverlayLogger.__single = self def getInstance(*args, **kw): if OverlayLogger.__single is None: OverlayLogger(*args, **kw) return OverlayLogger.__single getInstance = staticmethod(getInstance) def log(self, *msgs): log_msg = '' nmsgs = len(msgs) if nmsgs == 0: return else: for i in range(nmsgs-1): log_msg += msgs[i] log_msg += log_separator if msgs[nmsgs-1]: log_msg += msgs[nmsgs-1] if log_msg: if DEBUG: db_msg = '' if msgs[0].endswith('MSG'): for i in range(nmsgs-2): db_msg += msgs[i] db_msg += log_separator permid = msgs[nmsgs-2] s = encodestring(permid).replace("\n","") db_msg += encodestring(sha(s).digest()).replace("\n","") else: for i in range(nmsgs-1): db_msg += msgs[i] db_msg += log_separator permid = msgs[nmsgs-1] s = encodestring(permid).replace("\n","") db_msg += encodestring(sha(s).digest()).replace("\n","") print >> sys.stderr, "Logger: ", db_msg self.write_log(log_msg) def write_log(self, msg): # one logfile per day. today = get_today() if not hasattr(self, 'today'): self.today = today self.logger = self.make_logger() elif today != self.today: # make a new log if a new day comes self.logger.close() self.logger = self.make_logger() self.logger.log(3, msg) def make_logger(self): hostname = socket.gethostname() return Logger(3, self.file_name, self.file_dir, hostname, True) if __name__ == '__main__': create_logger('test.log') get_logger().log(1, 'abc' + ' ' + str(['abc', 1, (2,3)])) get_logger().log(0, [1,'a',{(2,3):'asfadf'}]) #get_logger().log(1, open('log').read())