@@ -22,7 +22,10 @@ class FluentRecordFormatter(logging.Formatter, object):
2222
2323 Best used with server storing data in an ElasticSearch cluster for example.
2424
25- :param fmt: a dict with format string as values to map to provided keys.
25+ :param fmt: a dict or a callable with format string as values to map to provided keys.
26+ If callable, should accept a single argument `LogRecord` and return a dict,
27+ and have a field `usesTime` that is callable and return a bool as would
28+ `FluentRecordFormatter.usesTime`
2629 :param datefmt: strftime()-compatible date/time format string.
2730 :param style: '%', '{' or '$' (used only with Python 3.2 or above)
2831 :param fill_missing_fmt_key: if True, do not raise a KeyError if the format
@@ -32,7 +35,7 @@ class FluentRecordFormatter(logging.Formatter, object):
3235 :param exclude_attrs: switches this formatter into a mode where all attributes
3336 except the ones specified by `exclude_attrs` are logged with the record as is.
3437 If `None`, operates as before, otherwise `fmt` is ignored.
35- Can be a `list`, `tuple` or a `set` .
38+ Can be an iterable .
3639 """
3740
3841 def __init__ (self , fmt = None , datefmt = None , style = '%' , fill_missing_fmt_key = False , format_json = True ,
@@ -63,12 +66,22 @@ def __init__(self, fmt=None, datefmt=None, style='%', fill_missing_fmt_key=False
6366 if exclude_attrs is not None :
6467 self ._exc_attrs = set (exclude_attrs )
6568 self ._fmt_dict = None
69+ self ._formatter = self ._format_by_exclusion
70+ self .usesTime = super (FluentRecordFormatter , self ).usesTime
6671 else :
6772 self ._exc_attrs = None
6873 if not fmt :
6974 self ._fmt_dict = basic_fmt_dict
75+ self ._formatter = self ._format_by_dict
76+ self .usesTime = self ._format_by_dict_uses_time
7077 else :
71- self ._fmt_dict = fmt
78+ if hasattr (fmt , "__call__" ):
79+ self ._formatter = fmt
80+ self .usesTime = fmt .usesTime
81+ else :
82+ self ._fmt_dict = fmt
83+ self ._formatter = self ._format_by_dict
84+ self .usesTime = self ._format_by_dict_uses_time
7285
7386 if format_json :
7487 self ._format_msg = self ._format_msg_json
@@ -90,37 +103,13 @@ def format(self, record):
90103 record .hostname = self .hostname
91104
92105 # Apply format
93- data = {}
94- if self ._exc_attrs is not None :
95- for key , value in record .__dict__ .items ():
96- if key not in self ._exc_attrs :
97- data [key ] = value
98- else :
99- for key , value in self ._fmt_dict .items ():
100- try :
101- if self .__style :
102- value = self .__style (value ).format (record )
103- else :
104- value = value % record .__dict__
105- except KeyError as exc :
106- value = None
107- if not self .fill_missing_fmt_key :
108- raise exc
109-
110- data [key ] = value
106+ data = self ._formatter (record )
111107
112108 self ._structuring (data , record )
113109 return data
114110
115111 def usesTime (self ):
116- if self ._exc_attrs is not None :
117- return super (FluentRecordFormatter , self ).usesTime ()
118- else :
119- if self .__style :
120- search = self .__style .asctime_search
121- else :
122- search = "%(asctime)"
123- return any ([value .find (search ) >= 0 for value in self ._fmt_dict .values ()])
112+ """This method is substituted on construction based on settings for performance reasons"""
124113
125114 def _structuring (self , data , record ):
126115 """ Melds `msg` into `data`.
@@ -153,6 +142,36 @@ def _format_msg_json(self, record, msg):
153142 def _format_msg_default (self , record , msg ):
154143 return {'message' : record .getMessage ()}
155144
145+ def _format_by_exclusion (self , record ):
146+ data = {}
147+ for key , value in record .__dict__ .items ():
148+ if key not in self ._exc_attrs :
149+ data [key ] = value
150+ return data
151+
152+ def _format_by_dict (self , record ):
153+ data = {}
154+ for key , value in self ._fmt_dict .items ():
155+ try :
156+ if self .__style :
157+ value = self .__style (value ).format (record )
158+ else :
159+ value = value % record .__dict__
160+ except KeyError as exc :
161+ value = None
162+ if not self .fill_missing_fmt_key :
163+ raise exc
164+
165+ data [key ] = value
166+ return data
167+
168+ def _format_by_dict_uses_time (self ):
169+ if self .__style :
170+ search = self .__style .asctime_search
171+ else :
172+ search = "%(asctime)"
173+ return any ([value .find (search ) >= 0 for value in self ._fmt_dict .values ()])
174+
156175 @staticmethod
157176 def _add_dic (data , dic ):
158177 for key , value in dic .items ():
0 commit comments