Skip to content

Commit 8c48387

Browse files
author
Bob Bui
committed
docs: add new example for web custom log and update readme
1 parent d71fdcf commit 8c48387

File tree

3 files changed

+73
-46
lines changed

3 files changed

+73
-46
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,10 @@ json_logging.config_root_logger()
211211
```
212212

213213
## 2.6 Custom log formatter
214-
Customer JSON log formatter can be passed to init method. see example for more detail:
215-
https://github.com/thangbn/json-logging-python/blob/master/example/custom_log_format.py
214+
Customer JSON log formatter can be passed to init method. see examples for more detail: [non web](https://github.com/thangbn/json-logging-python/blob/master/example/custom_log_format.py),
215+
[web](https://github.com/thangbn/json-logging-python/blob/master/example/custom_log_format_request.py)
216+
217+
216218

217219
## 2.7 Exclude certain URl from request instrumentation
218220
Certain URL can be excluded from request instrumentation by specifying a list of regex into **init_request_instrument** method like below:

example/custom_log_format.py

Lines changed: 10 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,37 @@
11
# This example shows how the logger can be set up to use a custom JSON format.
2-
import logging
32
import json
4-
import traceback
5-
from datetime import datetime
6-
import copy
7-
import json_logging
3+
import logging
84
import sys
95

10-
json_logging.ENABLE_JSON_LOGGING = True
6+
import json_logging
117

128

139
def extra(**kw):
1410
'''Add the required nested props layer'''
1511
return {'extra': {'props': kw}}
1612

1713

18-
class CustomJSONLog(logging.Formatter):
14+
class CustomJSONLog(json_logging.JSONLogFormatter):
1915
"""
2016
Customized logger
2117
"""
2218

23-
def get_exc_fields(self, record):
24-
if record.exc_info:
25-
exc_info = self.format_exception(record.exc_info)
26-
else:
27-
exc_info = record.exc_text
28-
return {'python.exc_info': exc_info}
29-
30-
@classmethod
31-
def format_exception(cls, exc_info):
32-
return ''.join(traceback.format_exception(*exc_info)) if exc_info else ''
33-
3419
def format(self, record):
35-
json_log_object = {"@timestamp": datetime.utcnow().isoformat(),
36-
"level": record.levelname,
37-
"message": record.getMessage(),
38-
"caller": record.filename + '::' + record.funcName
39-
}
40-
json_log_object['data'] = {
41-
"python.logger_name": record.name,
42-
"python.module": record.module,
43-
"python.funcName": record.funcName,
44-
"python.filename": record.filename,
45-
"python.lineno": record.lineno,
46-
"python.thread": record.threadName,
47-
"python.pid": record.process
48-
}
49-
if hasattr(record, 'props'):
50-
json_log_object['data'].update(record.props)
51-
52-
if record.exc_info or record.exc_text:
53-
json_log_object['data'].update(self.get_exc_fields(record))
20+
json_customized_log_object = ({
21+
"customized_prop": "customized value",
22+
"message": record.getMessage()
23+
})
5424

55-
return json.dumps(json_log_object)
25+
return json.dumps(json_customized_log_object)
5626

5727

5828
# You would normally import logger_init and setup the logger in your main module - e.g.
5929
# main.py
6030

61-
json_logging.init_non_web(custom_formatter=CustomJSONLog)
31+
json_logging.init_non_web(custom_formatter=CustomJSONLog, enable_json=True)
6232

6333
logger = logging.getLogger(__name__)
6434
logger.setLevel(logging.DEBUG)
6535
logger.addHandler(logging.StreamHandler(sys.stderr))
6636

67-
logger.info('Starting')
68-
try:
69-
1 / 0
70-
except: # noqa pylint: disable=bare-except
71-
logger.exception('You can\'t divide by zero')
37+
logger.info('sample log message')

example/custom_log_format_request.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import json
2+
import logging
3+
import sys
4+
5+
import flask
6+
7+
import json_logging
8+
9+
10+
class CustomRequestJSONLog(json_logging.JSONLogWebFormatter):
11+
"""
12+
Customized logger
13+
"""
14+
15+
def format(self, record):
16+
json_customized_log_object = ({
17+
"customized_prop": "customized value",
18+
"correlation_id": json_logging.get_correlation_id(),
19+
})
20+
return json.dumps(json_customized_log_object)
21+
22+
23+
app = flask.Flask(__name__)
24+
json_logging.init_flask(enable_json=True)
25+
json_logging.init_request_instrument(app, exclude_url_patterns=[r'/exclude_from_request_instrumentation'],
26+
custom_formatter=CustomRequestJSONLog)
27+
28+
# init the logger as usual
29+
logger = logging.getLogger("test logger")
30+
logger.setLevel(logging.DEBUG)
31+
logger.addHandler(logging.StreamHandler(sys.stdout))
32+
33+
34+
@app.route('/')
35+
def home():
36+
logger.info("test log statement")
37+
logger.info("test log statement with extra props", extra={'props': {"extra_property": 'extra_value'}})
38+
correlation_id = json_logging.get_correlation_id()
39+
return "hello world" \
40+
"\ncorrelation_id : " + correlation_id
41+
42+
43+
@app.route('/exception')
44+
def exception():
45+
try:
46+
raise RuntimeError
47+
except BaseException as e:
48+
logger.error("Error occurred", exc_info=e)
49+
logger.exception("Error occurred", exc_info=e)
50+
return "Error occurred, check log for detail"
51+
52+
53+
@app.route('/exclude_from_request_instrumentation')
54+
def exclude_from_request_instrumentation():
55+
return "this request wont log request instrumentation information"
56+
57+
58+
if __name__ == "__main__":
59+
app.run(host='0.0.0.0', port=int(5000), use_reloader=False)

0 commit comments

Comments
 (0)