タイトルのようなことをしたので記事にしておく。今回記事にする内容はほぼ次のコミットと同じ。

cahsper-flask: 764dafda89e0a563544eb0e1525bdf0ff4ade6d3

環境


  • Python: 3.8.6
  • Flask: 1.1.2

やること


APIサーバでリクエストがきたタイミングでログ出力する。

コード


ログ設定

ログはファイルに出力してほしかったので__init__.pyでログの設定を行う。

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
# app.__init__.py
import os

from flask import Flask
from logging.config import dictConfig

app = Flask(__name__)

dictConfig({
'version': 1,
'formatters': {
'file': {
'format': '[%(asctime)s] [%(levelname)s] : %(message)s',
}
},
'handlers': {
'file': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'formatter': 'file',
'filename': './logs/application.log'
}
},
'root': {
'level': 'WARN',
'handlers': ['file']
},
})

... 以下略

この設定は下記の記事を参考にした。

リクエストをログ出力するデコレータ

次にutils.logger.py(モジュール名などは任意)というファイルを作成して、そこにHTTPリクエストのログを出力するデコレータを書く。requestはグローバルコンテキストなので、importしてくるだけでいい。リクエストの情報が詰まっている。後はこれをイイ感じにログ出力する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# utils.logger.py
from flask import request
from functools import wraps
from app import app

def http_request_logging(f):
@wraps(f)
def decorated_function(*args, **kwargs):
try:
app.logger.info('%s - %s - %s - %s', request.remote_addr, request.method, request.url, request.query_string)
except Exception as e:
app.logger.exception(e)
pass
return f(*args, **kwargs)
return decorated_function

デコレータはただの高階関数のシンタックスシュガーだと考えれば別に難しくない。

コントローラに適用する

作成したデコレータをコントローラで使用する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import json

from flask import Blueprint, Response
from app.models.users import Users
from app.utils.logger import http_request_logging

module_users = Blueprint('users', __name__)

@module_users.route("/users/<user_name>", methods=['GET'], strict_slashes=False)
@http_request_logging
def get_user(user_name):
user = Users.find_by_name(user_name)

... 以下なんかの処理

これで、/users/JhonDoeとかにアクセスすると下記のようにログが残る。

1
[2020-10-13 22:49:47,644] [INFO] : 127.0.0.1 - GET - http://localhost:5000/users/JhonDoe - b''

クエリパラメータがない場合にb''と出力されているのが気になるが、まあ、こんな感じ。

所感


  • 本当はレスポンスのログをイイ感じに出したい
  • requestみたいなグローバルな空間にコンテキストを持ってるのがモニョモニョする