summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipsilon/util/log.py67
1 files changed, 64 insertions, 3 deletions
diff --git a/ipsilon/util/log.py b/ipsilon/util/log.py
index a010b16..857a5ba 100644
--- a/ipsilon/util/log.py
+++ b/ipsilon/util/log.py
@@ -3,8 +3,10 @@
# See the file named COPYING for the project license
import cherrypy
-import inspect
import cStringIO
+import inspect
+import os
+import traceback
def log_request_response():
'''Log the contents of the request and subsequent response.
@@ -246,10 +248,67 @@ cherrypy.tools.log_request_response = cherrypy.Tool('on_end_resource', log_reque
class Log(object):
+ @staticmethod
+ def stacktrace():
+ buf = cStringIO.StringIO()
+
+ stack = traceback.extract_stack()
+ traceback.print_list(stack[:-2], file=buf)
+
+ stacktrace_string = buf.getvalue()
+ buf.close()
+ return stacktrace_string
+
+ @staticmethod
+ def get_class_from_frame(frame_obj):
+ '''
+ Taken from:
+ http://stackoverflow.com/questions/2203424/
+ python-how-to-retrieve-class-information-from-a-frame-object
+
+ At the frame object level, there does not seem to be any way
+ to find the actual python function object that has been
+ called.
+
+ However, if your code relies on the common convention of naming
+ the instance parameter of a method self, then you could do this.
+ '''
+
+ args, _, _, value_dict = inspect.getargvalues(frame_obj)
+ # Is the functions first parameter named 'self'?
+ if len(args) and args[0] == 'self':
+ # in that case, 'self' will be referenced in value_dict
+ instance = value_dict.get('self', None)
+ if instance:
+ # return its class
+ return getattr(instance, '__class__', None)
+ # return None otherwise
+ return None
+
+ @staticmethod
+ def call_location():
+ frame = inspect.stack()[2]
+ frame_obj = frame[0]
+ filename = frame[1]
+ line_number = frame[2]
+ func = frame[3]
+
+ # Only report the last 3 components of the path
+ filename = os.sep.join(filename.split(os.sep)[-3:])
+
+ cls = Log.get_class_from_frame(frame_obj)
+ if cls:
+ location = '%s:%s %s.%s()' % \
+ (filename, line_number, cls.__name__, func)
+ else:
+ location = '%s:%s %s()' % (filename, line_number, func)
+ return location
+
+
def debug(self, fact):
if cherrypy.config.get('debug', False):
- s = inspect.stack()
- cherrypy.log('DEBUG(%s): %s' % (s[1][3], fact))
+ location = Log.call_location()
+ cherrypy.log('DEBUG(%s): %s' % (location, fact))
# for compatibility with existing code
_debug = debug
@@ -259,3 +318,5 @@ class Log(object):
def error(self, fact):
cherrypy.log.error('ERROR: %s' % fact)
+ if cherrypy.config.get('stacktrace_on_error', False):
+ cherrypy.log.error(Log.stacktrace())