import re
import traceback
import logging
+import logging.config
from activegrid.util.lang import *
+import activegrid.util.objutils as objutils
+import activegrid.util.sysutils as sysutils
LEVEL_FATAL = logging.FATAL
LEVEL_ERROR = logging.ERROR
LEVEL_INFO = logging.INFO
LEVEL_DEBUG = logging.DEBUG
+EXCEPTION_INFO = 'exceptionInfo'
+
+LOG_MODE_IDE = 1
+LOG_MODE_TESTRUN = 2
+LOG_MODE_RUN = 3
+def initLogging(mode):
+ configFile = None
+ if (mode == LOG_MODE_IDE):
+ configFile = os.getenv("AG_LOGCONFIG_IDE")
+ elif (mode == LOG_MODE_TESTRUN):
+ configFile = os.getenv("AG_LOGCONFIG_TESTRUN")
+ else:
+ configFile = os.getenv("AG_LOGCONFIG_RUN")
+ if ((configFile == None) or not os.path.exists(configFile)):
+ if (mode == LOG_MODE_IDE):
+ configFile = "IDELog"
+ elif (mode == LOG_MODE_TESTRUN):
+ configFile = "TestRunLog"
+ else:
+ configFile = "RunLog"
+ configFile = sysutils.mainModuleDir + "/py" + configFile + ".ini"
+ if (os.path.exists(configFile)):
+ fileConfig(configFile)
+ else:
+ defaultStream = sys.stderr
+ if (mode == LOG_MODE_RUN):
+ defaultStream = sys.stdout
+ handler = logging.StreamHandler(defaultStream)
+ handler.setLevel(logging.INFO)
+ handler.setFormatter(logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s"))
+ logging.getLogger().addHandler(handler)
+ return configFile
+
+ag_debugLogger = logging.getLogger("activegrid.debug")
+
+def log(logger, level, msg, *params):
+ if (logger == None):
+ logger = ag_debugLogger
+ apply(logger.log, (level, msg) + params)
+
+def fatal(logger, msg, *params):
+ apply(logger.fatal, (msg,) + params)
+
+def error(logger, msg, *params):
+ apply(logger.error, (msg,) + params)
+
+def warn(logger, msg, *params):
+ apply(logger.warn, (msg,) + params)
+
+def info(logger, msg, *params):
+ apply(logger.info, (msg,) + params)
+
+def debug(logger, msg, *params):
+ if (logger == None):
+ logger = ag_debugLogger
+ apply(logger.debug, (msg,) + params)
+
+def setLevelFatal(logger):
+ logger.setLevel(LEVEL_FATAL)
+
+def setLevelError(logger):
+ logger.setLevel(LEVEL_ERROR)
+
+def setLevelWarn(logger):
+ logger.setLevel(LEVEL_WARN)
+
+def setLevelInfo(logger):
+ logger.setLevel(LEVEL_INFO)
+
+def setLevelDebug(logger):
+ logger.setLevel(LEVEL_DEBUG)
+
+def isEnabledForError(logger):
+ return logger.isEnabledFor(LEVEL_ERROR)
+
+def isEnabledForWarn(logger):
+ return logger.isEnabledFor(LEVEL_WARN)
+
+def isEnabledForInfo(logger):
+ return logger.isEnabledFor(LEVEL_INFO)
+
+def isEnabledForDebug(logger):
+ return logger.isEnabledFor(LEVEL_DEBUG)
+
TEST_MODE_NONE = 0
TEST_MODE_DETERMINISTIC = 1
TEST_MODE_NON_DETERMINISTIC = 2
global agTestMode
return agTestMode
-def testMode(normalObj, testObj=None):
- if getTestMode() > TEST_MODE_NONE:
+def testMode(normalObj, testObj=None, nonDeterministicObj=None):
+ testMode = getTestMode()
+ if testMode > TEST_MODE_NONE:
+ if ((nonDeterministicObj != None) and (testMode == TEST_MODE_NON_DETERMINISTIC)):
+ return nonDeterministicObj
return testObj
return normalObj
def _fileNameReplacementPHP(match):
return "%s...%s" % (match.group(1), match.group(2).replace(os.sep, "/"))
-def getTraceback():
- extype, val, tb = sys.exc_info()
- tbs = "\n"
- for s in traceback.format_tb(tb):
- tbs += s
+def formatTraceback(tb=None):
+ if (tb == None):
+ extype, val, tb = sys.exc_info()
+ tbs = "\n" + "".join(traceback.format_tb(tb))
return tbs
+def formatExceptionCause(cause, stacktrace=False):
+ if (cause == None):
+ return ""
+ tbs = ""
+ if (stacktrace):
+ tbs = formatTraceback()
+ return "Caused by %s.%s: %s%s" % (cause.__module__, cause.__class__.__name__, str(cause), tbs)
+
+def addExceptionInfo(e, key, value):
+ if not hasattr(e, EXCEPTION_INFO):
+ try:
+ setattr(e, EXCEPTION_INFO, {})
+ except:
+ return # Make sure we still report the real exception even if we can't add the extra info
+ if not e.exceptionInfo.has_key(key): # Never overwrite exception info since we assume earlier info is more specific
+ e.exceptionInfo[key] = value
+
def reportException(out=None, stacktrace=False, diffable=False, exception=None):
- if (True): # exception == None):
+ exstr = exceptionToString(exception, stacktrace, diffable)
+ if (out == None):
+ print exstr
+ else:
+ print >> out, exstr
+
+def exceptionToString(exception=None, stacktrace=False, diffable=False):
+ if (exception == None):
extype, val, t = sys.exc_info()
else:
- extype = type(exception)
+ extype = objutils.typeToString(exception)
val = exception
if (stacktrace):
e,v,t = sys.exc_info()
exstr = removeFileRefs(str(val))
else:
exstr = str(val)
- if (out == None):
- print "Got Exception = %s: %s" % (extype, exstr)
- else:
- print >> out, "Got Exception = %s: %s" % (extype, exstr)
+ if hasattr(val, EXCEPTION_INFO):
+ firstTime = True
+ for infoKey, infoValue in getattr(val, EXCEPTION_INFO).items():
+ if firstTime:
+ prefix = " EXTRA INFO:"
+ firstTime = False
+ else:
+ prefix = ","
+ exstr += ("%s %s=%s" % (prefix, infoKey, infoValue))
+ result = "Got Exception = %s: %s" % (extype, exstr)
if (stacktrace):
fmt = traceback.format_exception(extype, val, t)
for s in fmt:
if (diffable):
s = removeFileRefs(s)
- if (out == None):
- print s
+ result = result + "\n" + s
+ return result
+
+def fileConfig(fname, defaults=None):
+ """
+ This is copied from logging.config so that we could fix the class lookup of
+ handlers. Previously handlers had to be defined in logging.handlers and we
+ need to be able to define our own.
+ """
+ import ConfigParser, string
+
+ cp = ConfigParser.ConfigParser(defaults)
+ if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
+ cp.readfp(fname)
+ else:
+ cp.read(fname)
+ #first, do the formatters...
+ flist = cp.get("formatters", "keys")
+ if len(flist):
+ flist = string.split(flist, ",")
+ formatters = {}
+ for form in flist:
+ sectname = "formatter_%s" % form
+ opts = cp.options(sectname)
+ if "format" in opts:
+ fs = cp.get(sectname, "format", 1)
else:
- print >> out, s
-
+ fs = None
+ if "datefmt" in opts:
+ dfs = cp.get(sectname, "datefmt", 1)
+ else:
+ dfs = None
+ f = logging.Formatter(fs, dfs)
+ formatters[form] = f
+ #next, do the handlers...
+ #critical section...
+ logging._acquireLock()
+ try:
+## try:
+ #first, lose the existing handlers...
+ logging._handlers.clear()
+ #now set up the new ones...
+ hlist = cp.get("handlers", "keys")
+ if len(hlist):
+ hlist = string.split(hlist, ",")
+ handlers = {}
+ fixups = [] #for inter-handler references
+ for hand in hlist:
+## try:
+ sectname = "handler_%s" % hand
+ classname = cp.get(sectname, "class")
+ opts = cp.options(sectname)
+ if "formatter" in opts:
+ fmt = cp.get(sectname, "formatter")
+ else:
+ fmt = ""
+ klass = None
+ try:
+ klass = eval(classname, vars(logging))
+ except:
+ pass
+ if (klass == None):
+ klass = objutils.classForName(classname)
+ args = cp.get(sectname, "args")
+ args = eval(args, vars(logging))
+ h = apply(klass, args)
+ if "level" in opts:
+ level = cp.get(sectname, "level")
+ h.setLevel(logging._levelNames[level])
+ if len(fmt):
+ h.setFormatter(formatters[fmt])
+ #temporary hack for FileHandler and MemoryHandler.
+ if klass == logging.handlers.MemoryHandler:
+ if "target" in opts:
+ target = cp.get(sectname,"target")
+ else:
+ target = ""
+ if len(target): #the target handler may not be loaded yet, so keep for later...
+ fixups.append((h, target))
+ handlers[hand] = h
+## except Exception, e: #if an error occurs when instantiating a handler, too bad
+## pass #this could happen e.g. because of lack of privileges
+ #now all handlers are loaded, fixup inter-handler references...
+ for fixup in fixups:
+ h = fixup[0]
+ t = fixup[1]
+ h.setTarget(handlers[t])
+ #at last, the loggers...first the root...
+ llist = cp.get("loggers", "keys")
+ llist = string.split(llist, ",")
+ llist.remove("root")
+ sectname = "logger_root"
+ root = logging.root
+ log = root
+ opts = cp.options(sectname)
+ if "level" in opts:
+ level = cp.get(sectname, "level")
+ log.setLevel(logging._levelNames[level])
+ for h in root.handlers[:]:
+ root.removeHandler(h)
+ hlist = cp.get(sectname, "handlers")
+ if len(hlist):
+ hlist = string.split(hlist, ",")
+ for hand in hlist:
+ log.addHandler(handlers[hand])
+ #and now the others...
+ #we don't want to lose the existing loggers,
+ #since other threads may have pointers to them.
+ #existing is set to contain all existing loggers,
+ #and as we go through the new configuration we
+ #remove any which are configured. At the end,
+ #what's left in existing is the set of loggers
+ #which were in the previous configuration but
+ #which are not in the new configuration.
+ existing = root.manager.loggerDict.keys()
+ #now set up the new ones...
+ for log in llist:
+ sectname = "logger_%s" % log
+ qn = cp.get(sectname, "qualname")
+ opts = cp.options(sectname)
+ if "propagate" in opts:
+ propagate = cp.getint(sectname, "propagate")
+ else:
+ propagate = 1
+ logger = logging.getLogger(qn)
+ if qn in existing:
+ existing.remove(qn)
+ if "level" in opts:
+ level = cp.get(sectname, "level")
+ logger.setLevel(logging._levelNames[level])
+ for h in logger.handlers[:]:
+ logger.removeHandler(h)
+ logger.propagate = propagate
+ logger.disabled = 0
+ hlist = cp.get(sectname, "handlers")
+ if len(hlist):
+ hlist = string.split(hlist, ",")
+ for hand in hlist:
+ logger.addHandler(handlers[hand])
+ #Disable any old loggers. There's no point deleting
+ #them as other threads may continue to hold references
+ #and by disabling them, you stop them doing any logging.
+ for log in existing:
+ root.manager.loggerDict[log].disabled = 1
+## except:
+## import traceback
+## ei = sys.exc_info()
+## traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
+## del ei
+ finally:
+ logging._releaseLock()