summaryrefslogtreecommitdiffstats
path: root/ipsilon/util/log.py
blob: 20016756092513ad3c9b85e424f076bb2b0acbbd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# Copyright (C) 2014 Ipsilon Project Contributors
#
# See the file named COPYING for the project license

import cherrypy
import cStringIO
import inspect
import os
import traceback

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):
            location = Log.call_location()
            cherrypy.log('DEBUG(%s): %s' % (location, fact))

    # for compatibility with existing code
    _debug = debug

    def log(self, fact):
        cherrypy.log(fact)

    def error(self, fact):
        cherrypy.log.error('ERROR: %s' % fact)
        if cherrypy.config.get('stacktrace_on_error', False):
            cherrypy.log.error(Log.stacktrace())