11
11
12
12
class LogstashFormatterBase (logging .Formatter ):
13
13
14
- def __init__ (self , message_type = 'Logstash' , tags = None , fqdn = False ):
14
+ limit_stacktrace = 0
15
+
16
+ def __init__ (self , message_type = 'Logstash' , tags = None , fqdn = False , limit_stacktrace = 0 , limit_string_fields = 0 , limit_containers = 0 ):
15
17
self .message_type = message_type
16
18
self .tags = tags if tags is not None else []
19
+ LogstashFormatterBase .limit_stacktrace = limit_stacktrace
20
+ self .limit_string_fields = limit_string_fields
21
+ self .limit_containers = limit_containers
17
22
18
23
if fqdn :
19
24
self .host = socket .getfqdn ()
20
25
else :
21
26
self .host = socket .gethostname ()
22
27
28
+ def limit_string_field (self , value ):
29
+ if self .limit_string_fields == 0 :
30
+ return value
31
+ return value [:self .limit_string_fields ] + (value [self .limit_string_fields :] and '...Truncated...' )
32
+
23
33
def get_extra_fields (self , record , first = True ):
24
34
# The list contains all the attributes listed in
25
35
# http://docs.python.org/library/logging.html#logrecord-attributes
@@ -31,40 +41,54 @@ def get_extra_fields(self, record, first=True):
31
41
'auth_token' , 'password' )
32
42
33
43
if sys .version_info < (3 , 0 ):
34
- easy_types = (basestring , bool , dict , float , int , long , list , type (None ))
44
+ easy_types = (basestring , bool , float , int , long , type (None ))
35
45
else :
36
- easy_types = (str , bool , dict , float , int , list , type (None ))
46
+ easy_types = (str , bool , float , int , type (None ))
37
47
containers = (dict , set , list )
38
48
fields = {}
39
49
if first :
40
50
for key , value in record .__dict__ .items ():
41
51
if key not in skip_list or not first :
42
52
if isinstance (value , containers ):
43
53
fields [key ] = self .get_extra_fields (value , first = False )
54
+ elif type (value ) == str :
55
+ fields [key ] = self .limit_string_field (value )
44
56
elif isinstance (value , easy_types ):
45
57
fields [key ] = value
46
58
else :
47
- fields [key ] = repr (value )
59
+ fields [key ] = self . limit_string_field ( repr (value ) )
48
60
elif type (record ) == dict :
61
+ counter = 0
49
62
for key , value in record .items ():
63
+ counter += 1
64
+ if self .limit_containers != 0 and counter > self .limit_containers :
65
+ fields ['WARNING' ] = "...Truncated..."
66
+ break
50
67
if isinstance (value , containers ):
51
68
fields [key ] = self .get_extra_fields (value , first = False )
69
+ elif type (value ) == str :
70
+ fields [key ] = self .limit_string_field (value )
52
71
elif isinstance (value , easy_types ):
53
72
fields [key ] = value
54
73
else :
55
- fields [key ] = repr (value )
74
+ fields [key ] = self . limit_string_field ( repr (value ) )
56
75
elif type (record ) == list or type (record ) == set :
57
76
tmp = []
77
+ counter = 0
58
78
for value in record :
79
+ counter += 1
80
+ if self .limit_containers != 0 and counter > self .limit_containers :
81
+ tmp .append ("...Truncated..." )
82
+ break
59
83
tmp .append (self .get_extra_fields (value , first = False ))
60
84
return tmp
61
85
else :
86
+ if type (record ) == str :
87
+ return self .limit_string_field (record )
62
88
if isinstance (record , easy_types ):
63
89
return record
64
90
else :
65
- return repr (record )
66
-
67
-
91
+ return self .limit_string_field (repr (record ))
68
92
69
93
return fields
70
94
@@ -97,7 +121,10 @@ def format_timestamp(cls, time):
97
121
98
122
@classmethod
99
123
def format_exception (cls , exc_info ):
100
- return '' .join (traceback .format_exception (* exc_info )) if exc_info else ''
124
+ stacktrace = '' .join (traceback .format_exception (* exc_info )) if exc_info else ''
125
+ if cls .limit_stacktrace == 0 :
126
+ return stacktrace
127
+ return stacktrace [:cls .limit_stacktrace ] + (stacktrace [cls .limit_stacktrace :] and '..' )
101
128
102
129
@classmethod
103
130
def serialize (cls , message ):
0 commit comments