Nonrepeated Logid in Each Flask Request

Coding after Climbing

Nonrepeated-logid is very useful to get what you want in thousands lines of logs, and make tracing log very easy in complicated system with many modules.

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import uuid
from functools import wraps
import logging
from logging.handlers import RotatingFileHandler


from flask import Flask, g


# improve performance if you don't need print thread info in log
logging.logThreads = 0
logging.logProcesses = 0
logging.logMultiprocessing = 0

formatter = logging.Formatter('%(asctime)s %(levelname)s [%(module)s:%(lineno)d] log_id[%(log_id)s] %(message)s')
file_handler = RotatingFileHandler('logs/test.log', maxBytes=10 * 1024 * 1024, backupCount=10)
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.INFO)

app = Flask(__name__)
app.logger.setLevel(logging.INFO)
app.logger.addHandler(file_handler)


@app.before_request
def setup():
# set logid for each request
# or you can get logid in upstream request
g.log_id = uuid.uuid4().hex
g.logger = logging.LoggerAdapter(app.logger, extra={'log_id': g.log_id})


def format_json_response(func):
@wraps(func)
def decorated(*args, **kwargs):
code, data = func(*args, **kwargs)
msg = 'success' if code == 0 else 'error'
resp = {
'code': code,
'data': data,
'log_id': g.log_id,
'msg': msg
}
return resp, 200
return decorated


@app.route('/test', methods=['GET'])
@format_json_response
def log_test():
print('test')
g.logger.info('test')
code = 0
resp = {'test': 1}
return code, resp


if __name__ == '__main__':
app.run(port=8888, debug=True)

Response

1
2
3
4
5
6
7
8
{
"code": 0,
"data": {
"test": 1
},
"log_id": "36165b74e8124c22a44300833be516cb",
"msg": "success"
}

Log file

1
2022-03-10 00:36:46,170 INFO [flask_log_demo:66] log_id[36165b74e8124c22a44300833be516cb] test