8
8
from django .utils .translation import ugettext_lazy as _
9
9
from debug_toolbar .panels import DebugPanel
10
10
11
- class ThreadTrackingHandler (logging .Handler ):
11
+
12
+ class LogCollector (object ):
12
13
def __init__ (self ):
13
14
if threading is None :
14
15
raise NotImplementedError ("threading module is not available, \
15
16
the logging panel cannot be used without it" )
16
- logging .Handler .__init__ (self )
17
17
self .records = {} # a dictionary that maps threads to log records
18
18
19
- def emit (self , record ):
20
- self .get_records ().append (record )
19
+ def add_record (self , record , thread = None ):
20
+ self .get_records (thread ).append (record )
21
21
22
22
def get_records (self , thread = None ):
23
23
"""
@@ -36,28 +36,75 @@ def clear_records(self, thread=None):
36
36
if thread in self .records :
37
37
del self .records [thread ]
38
38
39
- handler = ThreadTrackingHandler ()
39
+
40
+ class ThreadTrackingHandler (logging .Handler ):
41
+ def __init__ (self , collector ):
42
+ logging .Handler .__init__ (self )
43
+ self .collector = collector
44
+
45
+ def emit (self , record ):
46
+ record = {
47
+ 'message' : record .getMessage (),
48
+ 'time' : datetime .datetime .fromtimestamp (record .created ),
49
+ 'level' : record .levelname ,
50
+ 'file' : record .pathname ,
51
+ 'line' : record .lineno ,
52
+ 'channel' : record .name ,
53
+ }
54
+ self .collector .add_record (record )
55
+
56
+
57
+ collector = LogCollector ()
58
+ logging_handler = ThreadTrackingHandler (collector )
40
59
logging .root .setLevel (logging .NOTSET )
41
- logging .root .addHandler (handler )
60
+ logging .root .addHandler (logging_handler ) # register with logging
61
+
62
+ try :
63
+ import logbook
64
+ logbook_supported = True
65
+ except ImportError :
66
+ # logbook support is optional, so fail silently
67
+ logbook_supported = False
68
+
69
+ if logbook_supported :
70
+ class LogbookThreadTrackingHandler (logbook .handlers .Handler ):
71
+ def __init__ (self , collector ):
72
+ logbook .handlers .Handler .__init__ (self , bubble = True )
73
+ self .collector = collector
74
+
75
+ def emit (self , record ):
76
+ record = {
77
+ 'message' : record .message ,
78
+ 'time' : record .time ,
79
+ 'level' : record .level_name ,
80
+ 'file' : record .filename ,
81
+ 'line' : record .lineno ,
82
+ 'channel' : record .channel ,
83
+ }
84
+ self .collector .add_record (record )
85
+
86
+
87
+ logbook_handler = LogbookThreadTrackingHandler (collector )
88
+ logbook_handler .push_application () # register with logbook
42
89
43
90
class LoggingPanel (DebugPanel ):
44
91
name = 'Logging'
45
92
has_content = True
46
93
47
94
def process_request (self , request ):
48
- handler .clear_records ()
95
+ collector .clear_records ()
49
96
50
97
def get_and_delete (self ):
51
- records = handler .get_records ()
52
- handler .clear_records ()
98
+ records = collector .get_records ()
99
+ collector .clear_records ()
53
100
return records
54
101
55
102
def nav_title (self ):
56
103
return _ ("Logging" )
57
104
58
105
def nav_subtitle (self ):
59
106
# FIXME l10n: use ngettext
60
- return "%s message%s" % (len (handler .get_records ()), (len (handler .get_records ()) == 1 ) and '' or 's' )
107
+ return "%s message%s" % (len (collector .get_records ()), (len (collector .get_records ()) == 1 ) and '' or 's' )
61
108
62
109
def title (self ):
63
110
return _ ('Log Messages' )
@@ -66,16 +113,7 @@ def url(self):
66
113
return ''
67
114
68
115
def content (self ):
69
- records = []
70
- for record in self .get_and_delete ():
71
- records .append ({
72
- 'message' : record .getMessage (),
73
- 'time' : datetime .datetime .fromtimestamp (record .created ),
74
- 'level' : record .levelname ,
75
- 'file' : record .pathname ,
76
- 'line' : record .lineno ,
77
- })
78
-
116
+ records = self .get_and_delete ()
79
117
context = self .context .copy ()
80
118
context .update ({'records' : records })
81
119
0 commit comments