@@ -151,22 +151,29 @@ def __init(framework_name=None, custom_formatter=None):
151151 util .update_formatter_for_loggers (existing_loggers , formatter )
152152
153153
154- def init_request_instrument (app = None ):
154+ def init_request_instrument (app = None , custom_formatter = None ):
155155 """
156156 Configure the request instrumentation logging configuration for given web app. Must be called after init method
157157
158+ If **custom_formatter** is passed, it will use this formatter over the default.
159+
158160 :param app: current web application instance
161+ :param custom_formatter: formatter to override default JSONRequestLogFormatter.
159162 """
160163
161164 if _current_framework is None or _current_framework == '-' :
162165 raise RuntimeError ("please init the logging first, call init(framework_name) first" )
166+
167+ if custom_formatter :
168+ if not issubclass (custom_formatter , logging .Formatter ):
169+ raise ValueError ('custom_formatter is not subclass of logging.Formatter' , custom_formatter )
163170
164171 configurator = _current_framework ['app_request_instrumentation_configurator' ]()
165172 configurator .config (app )
166173
167- handlers = configurator . request_logger . handlers
168- for handler in handlers :
169- handler . setFormatter ( JSONRequestLogFormatter () )
174+ formatter = custom_formatter if custom_formatter else JSONRequestLogFormatter
175+ logger = configurator . request_logger
176+ util . update_formatter_for_loggers ([ logger ], formatter )
170177
171178
172179def get_request_logger ():
@@ -212,25 +219,40 @@ def update_response_status(self, response):
212219 self .response_sent_at = util .iso_time_format (utcnow )
213220
214221
215- class JSONRequestLogFormatter (logging .Formatter ):
222+ class BaseJSONFormatter (logging .Formatter ):
216223 """
217- Formatter for HTTP request instrumentation logging
224+ Base class for JSON formatters
218225 """
219226
220227 def format (self , record ):
221- utcnow = datetime .utcnow ()
222- request = record .request_info .request
223- request_adapter = _request_util .request_adapter
228+ log_object = self ._format_log_object (record , request_util = _request_util )
229+ return JSON_SERIALIZER (log_object )
224230
225- length = request_adapter . get_content_length ( request )
226- json_log_object = {
227- "type" : "request" ,
231+ def _format_log_object ( self , record , request_util ):
232+ utcnow = datetime . utcnow ()
233+ return {
228234 "written_at" : util .iso_time_format (utcnow ),
229235 "written_ts" : util .epoch_nano_second (utcnow ),
230236 "component_id" : COMPONENT_ID ,
231237 "component_name" : COMPONENT_NAME ,
232238 "component_instance" : COMPONENT_INSTANCE_INDEX ,
233- "correlation_id" : _request_util .get_correlation_id (request ),
239+ }
240+
241+
242+ class JSONRequestLogFormatter (BaseJSONFormatter ):
243+ """
244+ Formatter for HTTP request instrumentation logging
245+ """
246+
247+ def _format_log_object (self , record , request_util ):
248+ json_log_object = super ()._format_log_object (record , request_util )
249+ request = record .request_info .request
250+ request_adapter = request_util .request_adapter
251+
252+ length = request_adapter .get_content_length (request )
253+ json_log_object .update ({
254+ "type" : "request" ,
255+ "correlation_id" : request_util .get_correlation_id (request ),
234256 "remote_user" : request_adapter .get_remote_user (request ),
235257 "request" : request_adapter .get_path (request ),
236258 "referer" : request_adapter .get_http_header (request , 'referer' , EMPTY_VALUE ),
@@ -246,15 +268,17 @@ def format(self, record):
246268 "response_status" : record .request_info .response_status ,
247269 "response_size_b" : record .request_info .response_size_b ,
248270 "response_content_type" : record .request_info .response_content_type ,
249- "response_sent_at" : record .request_info .response_sent_at }
250- return JSON_SERIALIZER (json_log_object )
271+ "response_sent_at" : record .request_info .response_sent_at
272+ })
273+ return json_log_object
274+
251275
252276
253277def _sanitize_log_msg (record ):
254278 return record .getMessage ().replace ('\n ' , '_' ).replace ('\r ' , '_' ).replace ('\t ' , '_' )
255279
256280
257- class JSONLogFormatter (logging . Formatter ):
281+ class JSONLogFormatter (BaseJSONFormatter ):
258282 """
259283 Formatter for non-web application log
260284 """
@@ -271,77 +295,39 @@ def get_exc_fields(self, record):
271295
272296 @classmethod
273297 def format_exception (cls , exc_info ):
274-
275298 return '' .join (traceback .format_exception (* exc_info )) if exc_info else ''
276299
277- def format (self , record ):
278- utcnow = datetime .utcnow ()
279- json_log_object = {"type" : "log" ,
280- "written_at" : util .iso_time_format (utcnow ),
281- "written_ts" : util .epoch_nano_second (utcnow ),
282- "component_id" : COMPONENT_ID ,
283- "component_name" : COMPONENT_NAME ,
284- "component_instance" : COMPONENT_INSTANCE_INDEX ,
285- "logger" : record .name ,
286- "thread" : record .threadName ,
287- "level" : record .levelname ,
288- "line_no" : record .lineno ,
289- "module" : record .module ,
290- "msg" : _sanitize_log_msg (record ),
291- }
300+ def _format_log_object (self , record , request_util ):
301+ json_log_object = super ()._format_log_object (record , request_util )
302+ json_log_object .update ({
303+ "type" : "log" ,
304+ "logger" : record .name ,
305+ "thread" : record .threadName ,
306+ "level" : record .levelname ,
307+ "module" : record .module ,
308+ "line_no" : record .lineno ,
309+ "msg" : _sanitize_log_msg (record ),
310+ })
292311 if hasattr (record , 'props' ):
293312 json_log_object .update (record .props )
294313
295314 if record .exc_info or record .exc_text :
296315 json_log_object .update (self .get_exc_fields (record ))
297316
298- return JSON_SERIALIZER ( json_log_object )
317+ return json_log_object
299318
300319
301- class JSONLogWebFormatter (logging . Formatter ):
320+ class JSONLogWebFormatter (JSONLogFormatter ):
302321 """
303322 Formatter for web application log
304323 """
305324
306- def get_exc_fields (self , record ):
307- if record .exc_info :
308- exc_info = self .format_exception (record .exc_info )
309- else :
310- exc_info = record .exc_text
311- return {
312- 'exc_info' : exc_info ,
313- 'filename' : record .filename ,
314- }
315-
316- @classmethod
317- def format_exception (cls , exc_info ):
318-
319- return '' .join (traceback .format_exception (* exc_info )) if exc_info else ''
320-
321- def format (self , record ):
322- utcnow = datetime .utcnow ()
323- json_log_object = {"type" : "log" ,
324- "written_at" : util .iso_time_format (utcnow ),
325- "written_ts" : util .epoch_nano_second (utcnow ),
326- "component_id" : COMPONENT_ID ,
327- "component_name" : COMPONENT_NAME ,
328- "component_instance" : COMPONENT_INSTANCE_INDEX ,
329- "logger" : record .name ,
330- "thread" : record .threadName ,
331- "level" : record .levelname ,
332- "module" : record .module ,
333- "line_no" : record .lineno ,
334- "correlation_id" : _request_util .get_correlation_id (),
335- "msg" : _sanitize_log_msg (record )
336- }
337-
338- if hasattr (record , 'props' ):
339- json_log_object .update (record .props )
340-
341- if record .exc_info or record .exc_text :
342- json_log_object .update (self .get_exc_fields (record ))
343-
344- return JSON_SERIALIZER (json_log_object )
325+ def _format_log_object (self , record , request_util ):
326+ json_log_object = super ()._format_log_object (record , request_util )
327+ json_log_object .update ({
328+ "correlation_id" : request_util .get_correlation_id (),
329+ })
330+ return json_log_object
345331
346332
347333# register flask support
0 commit comments