首先,是要記錄每個請求的日志,在每個接口函數(shù)中都記錄日志的話,代碼量看著比較大而且不美觀,于是想到能不能用一個函數(shù)進(jìn)行統(tǒng)一的處理,這個時候flask的鉤子函數(shù)們又要派上用場啦。
- 在 before_app_request 中記錄每個請求的記錄
開發(fā)的過程中采用了前后端分離,前后端通過json格式進(jìn)行數(shù)據(jù)交互,涉及到文件上傳的個別接口使用了表單的提交方式,代碼如下:
@api.before_app_request
def before_app_request():
api_name = request.url
try:
#收到的前端數(shù)據(jù)
request_data = json.loads(request.get_data())
except Exception as e:
request_data = request.form.to_dict()
redis_log_format('R', api_name, None, str(request_data))
- 在 after_app_request 中記錄每個請求對應(yīng)的響應(yīng)記錄
@api.after_app_request
def after_app_request(response):
api_name = request.url
#返回給前端的數(shù)據(jù),全部為json類型
response_data = response.json
if str(response.status_code).startswith('4') or str(response.status_code).startswith('5') :
redis_log_format('E', api_name, response.status_code, str(response_data))
else:
redis_log_format('I', api_name, response.status_code, str(response_data))
#別忘記將response返回,否則數(shù)據(jù)到不了前端
return response
- 用函數(shù)事先約定好日志記錄的格式
為了減小IO操作對程序效率的影響,也為了避免多進(jìn)程進(jìn)行IO操作時帶來的沖突,可以先把日志存到redis中,之后再用異步線程或者單獨的進(jìn)程將redis中的日志按照日期讀到磁盤文件中,代碼如下:
def redis_log_format(level, url, status_code, message): #status_code為狀態(tài)碼,請求日志中為None
# 定義日志的層級
level_dict = { "I":"INFO", "W":"WARNING", "E":"ERROR", 'R':"REQUEST"}
now = datetime.now()
asctime = now.strftime('%Y-%m-%d %H:%M:%S')
levelname = level_dict.get(level, 'INFO')
process = os.getpid()
thread = threading.currentThread().ident
#定義日志的格式 采用f‘’的方式格式化字符串
strMessage = f'{asctime} {levelname} {process} {thread} {url} {status_code} {message}'
#將日志存放到redis中的有序集合中,用時間戳作為每條日志的得分,同一天的日志放到一個集合中,便于之后按日期保存日志文件
tablename = str(date.today())
score= int(now.strftime('%Y%m%d%H%M%S'))
r.zadd( tablename, { strMessage:score } )