import time _loggers = dict() def getLogger(filename): ''' Get logger for C{filename} @param filename: Filename ''' if not _loggers.has_key(filename): _loggers[filename] = FileLogger(filename) return _loggers[filename] def _logmethod(methodname, log): def _method(self,*argl,**argd): #parse the arguments and create a string representation args = [] for item in argl: args.append('%s' % str(item)) for key,item in argd.items(): args.append('%s=%s' % (key,str(item))) argstr = ','.join(args) # do the actual method call returnval = getattr(self,'_H_%s' % methodname)(*argl,**argd) log.debug("%s called with: (%s) returning: %s" % (methodname,argstr, str(returnval))) return returnval return _method class Logger: ''' Logger class. @cvar DEBUG: Debug level @cvar INFO: Info leevl @cvar WARNING: Warning level @cvar ERROR: Error level ''' DEBUG = 4 INFO = 3 WARNING = 2 ERROR = 1 def __init__(self, callback, level): ''' Constructor. @param callback: Callback function to send log messages to @param level: Log level ''' self.log = [] self.callback = callback self.level = level def getLevel(self): ''' Get log level @return: Current logging level ''' return self.level def setLevel(self, level): ''' Set a new log level @param level: Log level ''' self.level = level def setCallback(self, callback): ''' Set a new callback function @param callback: Callback function to send log messages to ''' self.callback = callback def info(self, message): ''' Log INFO message @param message: ''' self.doLog(message, self.INFO) def debug(self, message): ''' Log DEBUG message @param message: ''' self.doLog(message, self.DEBUG) def warning(self, message): ''' Log WARNING message @param message: ''' self.doLog(message, self.WARNING) def error(self, message): ''' Log ERROR message @param message: ''' self.doLog(message, self.ERROR) def doLog(self, message, level): ''' Log the message. If a callback function is defined, call that function with the log message @param message: Log Message @param level: Log Level ''' msg = LogMessage(message, level) self.log.append( msg ) if (level <= self.level and self.callback != None): self.callback( str(msg) ) class LogMessage: ''' Log message class. @cvar LEVELS: Textual represenation of Logger levels ''' LEVELS = { Logger.DEBUG: "DEBUG", Logger.INFO: "INFO", Logger.WARNING: "WARNING", Logger.ERROR: "ERROR" } def __init__(self, msg, level): ''' Constructor. @param msg: Logger message @param level: Logger level ''' self.message = msg self.level = level self.timestamp = time.ctime( time.time() ) def getLevel(self): ''' Get log level @return: Log level ''' return self.level def getMessage(self): ''' Get Log message @return: Log message ''' return self.message def getTimestamp(self): ''' Get timestamp log entry was made @return: Timestamp log entry was made ''' return self.timestamp def __repr__(self): ''' String representation @return: String representation of log message: TIMESTAMP LEVEL - MESSAGE ''' return "%s %s - %s\n" % (self.timestamp, str(self.LEVELS[self.level]), self.message) class FileLogger(Logger): ''' FileLogger is a Logger class that logs to a file ''' def __init__(self, filename): ''' Constructor. Initialize the logger and open the file @param filename: Filename to log to ''' self.filename = filename Logger.__init__(self, callback=self.logToFile, level=Logger.DEBUG) self.file = file(filename, "ab+") def logToFile(self, msg): ''' Logging callback Write the log message to the file @param msg: Log message ''' self.file.write("%s\n" % msg) self.file.flush() class LogMethodWrapper(type): log = getLogger("pyscrabble_server.log") def __new__(cls,classname,bases,classdict): for attr,item in classdict.items(): if callable(item): classdict['_H_%s'%attr] = item # rebind the method classdict[attr] = _logmethod(attr, LogMethodWrapper.log) # replace method by wrapper return type.__new__(cls,classname,bases,classdict)