3
3
import sys
4
4
import msgpack
5
5
import socket
6
- import threading
6
+ import traceback
7
+ from datetime import datetime
7
8
8
9
try :
9
10
import json
13
14
from fluent import sender
14
15
15
16
class FluentRecordFormatter (object ):
16
- def __init__ (self ):
17
+ def __init__ (self , encoding = 'utf-8' ):
17
18
self .hostname = socket .gethostname ()
19
+ self .fsencoding = sys .getfilesystemencoding ()
20
+ self .encoding = encoding
18
21
19
22
def format (self , record ):
20
23
data = {
21
- 'sys_host' : self .hostname ,
22
- 'sys_name' : record .name ,
23
- 'sys_module' : record .module ,
24
- # 'sys_lineno' : record.lineno,
25
- # 'sys_levelno' : record.levelno,
26
- # 'sys_levelname' : record.levelname,
27
- # 'sys_filename' : record.filename,
28
- # 'sys_funcname' : record.funcName,
29
- # 'sys_exc_info' : record.exc_info,
30
- }
31
- # if 'sys_exc_info' in data and data['sys_exc_info']:
32
- # data['sys_exc_info'] = self.formatException(data['sys_exc_info'])
33
-
34
- self ._structuring (data , record .msg )
24
+ u'time' : datetime .fromtimestamp (record .created ).isoformat (),
25
+ u'sys_msecs' : record .msecs ,
26
+ u'sys_host' : self ._decode (self .hostname ),
27
+ u'sys_name' : self ._asciidecode (record .name ),
28
+ u'sys_exc_info' : self ._format_exception (record .exc_info ),
29
+ u'sys_levelno' : record .levelno ,
30
+ u'sys_levelname' : self ._decode (record .levelname ),
31
+ u'sys_lineno' : record .lineno ,
32
+ u'sys_module' : self ._decode (record .module ),
33
+ u'sys_filename' : self ._fsdecode (record .filename ),
34
+ u'sys_funcname' : self ._decode (record .funcName ),
35
+ u'sys_process' : record .process ,
36
+ u'sys_processname' : self ._decode (record .processName ),
37
+ u'sys_thread' : record .thread ,
38
+ u'sys_threadname' : self ._decode (record .threadName ),
39
+ u'message' : self ._decode (self ._format_message (record .msg , record .args ))
40
+ }
35
41
return data
36
42
37
- def _structuring (self , data , msg ):
38
- if isinstance (msg , dict ):
39
- self ._add_dic (data , msg )
40
- elif isinstance (msg , str ):
41
- try :
42
- self ._add_dic (data , json .loads (str (msg )))
43
- except :
44
- pass
43
+ def _decode (self , value ):
44
+ if value is None :
45
+ return None
46
+ elif isinstance (value , str ):
47
+ return unicode (value , self .encoding )
48
+ elif isinstance (value , unicode ):
49
+ return value
50
+ else :
51
+ return self ._decode (str (value ))
52
+
53
+ def _fsdecode (self , value ):
54
+ if value is None :
55
+ return None
56
+ elif isinstance (value , str ):
57
+ return unicode (value , self .fsencoding )
58
+ elif isinstance (value , unicode ):
59
+ return value
60
+ else :
61
+ return '-'
62
+
63
+ def _asciidecode (self , value ):
64
+ if value is None :
65
+ return None
66
+ elif isinstance (value , str ):
67
+ return unicode (value )
68
+ elif isinstance (value , unicode ):
69
+ return value
70
+ else :
71
+ return self ._asciidecode (str (value ))
72
+
73
+ def _format_message (self , msg , args ):
74
+ if isinstance (msg , basestring ):
75
+ if args :
76
+ return msg % args
77
+ else :
78
+ return msg
79
+ else :
80
+ return msg
45
81
46
- def _add_dic (self , data , dic ):
47
- for k , v in dic .items ():
48
- if isinstance (k , str ) or isinstance (k , unicode ):
49
- data [str (k )] = v
82
+ def _format_exception (self , exc_info ):
83
+ if exc_info is not None and exc_info [0 ] is not None :
84
+ return {
85
+ 'type' : exc_info [0 ].__name__ ,
86
+ 'value' : exc_info [1 ].args ,
87
+ 'traceback' : traceback .extract_tb (exc_info [2 ])
88
+ }
89
+ else :
90
+ return None
50
91
51
92
class FluentHandler (logging .Handler ):
52
93
'''
@@ -69,7 +110,7 @@ def __init__(self,
69
110
def emit (self , record ):
70
111
if record .levelno < self .level : return
71
112
data = self .fmt .format (record )
72
- self .sender .emit (None , data )
113
+ self .sender .emit_with_time (None , record . created , data )
73
114
74
115
def _close (self ):
75
116
self .sender ._close ()
0 commit comments