@@ -151,22 +151,29 @@ def __init(framework_name=None, custom_formatter=None):
151
151
util .update_formatter_for_loggers (existing_loggers , formatter )
152
152
153
153
154
- def init_request_instrument (app = None ):
154
+ def init_request_instrument (app = None , custom_formatter = None ):
155
155
"""
156
156
Configure the request instrumentation logging configuration for given web app. Must be called after init method
157
157
158
+ If **custom_formatter** is passed, it will use this formatter over the default.
159
+
158
160
:param app: current web application instance
161
+ :param custom_formatter: formatter to override default JSONRequestLogFormatter.
159
162
"""
160
163
161
164
if _current_framework is None or _current_framework == '-' :
162
165
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 )
163
170
164
171
configurator = _current_framework ['app_request_instrumentation_configurator' ]()
165
172
configurator .config (app )
166
173
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 )
170
177
171
178
172
179
def get_request_logger ():
@@ -212,25 +219,40 @@ def update_response_status(self, response):
212
219
self .response_sent_at = util .iso_time_format (utcnow )
213
220
214
221
215
- class JSONRequestLogFormatter (logging .Formatter ):
222
+ class BaseJSONFormatter (logging .Formatter ):
216
223
"""
217
- Formatter for HTTP request instrumentation logging
224
+ Base class for JSON formatters
218
225
"""
219
226
220
227
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 )
224
230
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 {
228
234
"written_at" : util .iso_time_format (utcnow ),
229
235
"written_ts" : util .epoch_nano_second (utcnow ),
230
236
"component_id" : COMPONENT_ID ,
231
237
"component_name" : COMPONENT_NAME ,
232
238
"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 ),
234
256
"remote_user" : request_adapter .get_remote_user (request ),
235
257
"request" : request_adapter .get_path (request ),
236
258
"referer" : request_adapter .get_http_header (request , 'referer' , EMPTY_VALUE ),
@@ -246,15 +268,17 @@ def format(self, record):
246
268
"response_status" : record .request_info .response_status ,
247
269
"response_size_b" : record .request_info .response_size_b ,
248
270
"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
+
251
275
252
276
253
277
def _sanitize_log_msg (record ):
254
278
return record .getMessage ().replace ('\n ' , '_' ).replace ('\r ' , '_' ).replace ('\t ' , '_' )
255
279
256
280
257
- class JSONLogFormatter (logging . Formatter ):
281
+ class JSONLogFormatter (BaseJSONFormatter ):
258
282
"""
259
283
Formatter for non-web application log
260
284
"""
@@ -271,77 +295,39 @@ def get_exc_fields(self, record):
271
295
272
296
@classmethod
273
297
def format_exception (cls , exc_info ):
274
-
275
298
return '' .join (traceback .format_exception (* exc_info )) if exc_info else ''
276
299
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
+ })
292
311
if hasattr (record , 'props' ):
293
312
json_log_object .update (record .props )
294
313
295
314
if record .exc_info or record .exc_text :
296
315
json_log_object .update (self .get_exc_fields (record ))
297
316
298
- return JSON_SERIALIZER ( json_log_object )
317
+ return json_log_object
299
318
300
319
301
- class JSONLogWebFormatter (logging . Formatter ):
320
+ class JSONLogWebFormatter (JSONLogFormatter ):
302
321
"""
303
322
Formatter for web application log
304
323
"""
305
324
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
345
331
346
332
347
333
# register flask support
0 commit comments