-# Copyright 2004 James Bunton <james@delx.cjb.net>
+# Copyright 2004-2005 James Bunton <james@delx.cjb.net>
# Licensed for distribution under the GPL version 2, check COPYING for details
-import os
-import sys
-import config
-import utils
-import time
-
-""" A simple logging module. Use as follows.
-
-> import debug
-> debug.log("text string")
-
-If debugging is enabled then the data will be dumped to a file
-or the screen (whichever the user chose)
-"""
+from twisted.python import log
+import sys, time
-file = None
-rollingStack = None
-if(config.debugSmart):
- rollingStack = utils.RollingStack(100)
+import config
-def reopenFile(first=False):
- global file
- if(file or first):
- if(file): file.close()
+def observer(eventDict):
+ try:
+ observer2(eventDict)
+ except Exception, e:
+ printf("CRITICAL: Traceback in debug.observer2 - " + str(e))
+
+
+def observer2(eventDict):
+ edm = eventDict['message']
+ if isinstance(edm, LogEvent):
+ if edm.category == INFO and config._debugLevel < 3:
+ return
+ if (edm.category == WARN or edm.category == ERROR) and config._debugLevel < 2:
+ return
+ text = str(edm)
+ elif edm:
+ if config._debugLevel < 3: return
+ text = ' '.join(map(str, edm))
+ else:
+ if eventDict['isError'] and eventDict.has_key('failure'):
+ if config._debugLevel < 1: return
+ text = eventDict['failure'].getTraceback()
+ elif eventDict.has_key('format'):
+ if config._debugLevel < 3: return
+ text = eventDict['format'] % eventDict
+ else:
+ return
+
+ # Now log it!
+ timeStr = time.strftime("[%Y-%m-%d %H:%M:%S]", time.localtime(eventDict['time']))
+ text = text.replace("\n", "\n\t")
+ global debugFile
+ debugFile.write("%s %s\n" % (timeStr, text))
+ debugFile.flush()
+
+def printf(text):
+ sys.__stdout__.write(text + "\n")
+ sys.__stdout__.flush()
+
+
+debugFile = None
+def reloadConfig():
+ global debugFile
+ if debugFile:
+ debugFile.close()
+
+ try:
+ config._debugLevel = int(config.debugLevel.strip())
+ except ValueError:
+ config._debugLevel = 0
+ config.debugLevel = "0"
+
+ if config._debugLevel > 0:
+ if len(config.debugFile) > 0:
+ try:
+ debugFile = open(config.debugFile, "a")
+ log.msg("Reopened log file.")
+ except IOError:
+ log.discardLogs() # Give up
+ debugFile = sys.__stdout__
+ return
+ else:
+ debugFile = sys.__stdout__
try:
- file = open(utils.doPath(config.debugLog), 'a')
- except:
- print "Error opening debug log file. Exiting..."
- os.abort()
-
-
-def flushDebugSmart():
- global rollingStack
- if(config.debugSmart):
- file.write(rollingStack.grabAll())
- rollingStack.flush()
- file.flush()
-
-
-if(config.debugOn):
- if(len(config.debugLog) > 0):
- reopenFile(True)
- def log(data, wtime=True):
- text = ""
- if(wtime):
- text += time.strftime("%D - %H:%M:%S - ")
- text += utils.latin1(data) + "\n"
- if(config.debugSmart):
- rollingStack.push(text)
- else:
- file.write(text)
- file.flush()
+ log.removeObserver(observer)
+ except ValueError:
+ pass
+ log.startLoggingWithObserver(observer)
else:
- def log(data, wtime=True):
- if(wtime):
- print time.strftime("%D - %H:%M:%S - "),
- print utils.latin1(data)
- sys.stdout.flush()
- log("Debug logging enabled.")
-else:
- def log(data):
- pass
-
-
-def write(data):
- # So that I can pass this module to twisted.python.failure.Failure.printDetailedTraceback() as a file
- data = data.rstrip()
- log(data)
+ log.discardLogs()
+
+class INFO : pass
+class WARN : pass
+class ERROR: pass
+
+class LogEvent:
+ def __init__(self, category=INFO, ident="", msg="", log=True):
+ self.category, self.ident, self.msg = category, ident, msg
+ frame = sys._getframe(1)
+ # Get the class name
+ s = str(frame.f_locals.get("self", frame.f_code.co_filename))
+ self.klass = s[s.find(".")+1:s.find(" ")]
+ self.method = frame.f_code.co_name
+ self.args = frame.f_locals
+ if log:
+ self.log()
+
+ def __str__(self):
+ args = {}
+ for key in self.args.keys():
+ if key == "self":
+ args["self"] = "instance"
+ continue
+ val = self.args[key]
+ args[key] = val
+ try:
+ if len(val) > 128:
+ args[key] = "Oversize arg"
+ except:
+ # If its not an object with length, assume that it can't be too big. Hope that's a good assumption.
+ pass
+ category = str(self.category).split(".")[1]
+ return "%s :: %s :: %s :: %s :: %s :: %s" % (category, str(self.ident), self.msg, self.method, str(self.klass), str(args))
+
+ def log(self):
+ log.msg(self)
+