關於Flask日誌記錄,網上的文章大多都已過時,我在項目開發過程中,結合實際情況,初步採用以下日誌方案,後續遇到問題會不斷進行優化,並更新文章內容。
日誌記錄的總體思路如下:
- 在 Flask 工廠函數中,利用鉤子函數,將接口每次的請求參數和響應內容寫入到日誌文件中,並利用
flask_sqlalchemy
提供的get_debug_queries
方法,實現當執行時間超過閾值時,將查詢信息按照指定的格式寫入到日誌文件中; - 接入
Sentry SDK
,收集項目錯誤日誌,然後在Sentry Dashboard查看異常信息;(點擊查看官方文檔)
工廠函數相關內容如下,註釋已經寫得很清楚了:
from pathlib import Path
from logging.handlers import RotatingFileHandler
from flask import Flask
from flask_sqlalchemy import get_debug_queries
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
from .config import config
# 遞歸創建日誌存放目錄
basedir = Path(__file__).parent.parent # 項目根目錄
logdir = basedir.joinpath(r'rethink/logs')
if not logdir.is_dir():
os.makedirs(logdir)
# 初始化Sentry, 必須在工廠函數之前
sentry_sdk.init(
dsn="官網註冊賬號後會給出",
integrations=[FlaskIntegration()]
)
def make_app(config_name=None):
if config_name is None:
config_name = os.getenv("FLASK_CONFIG", "development")
# 加載配置文件
app = Flask(__name__)
app.config.from_object(config[config_name])
register_logger(app) # 註冊日誌處理器
# 如果沒有未處理的異常拋出,會在每個請求結束後運行
# 必須接受一個響應類對象作爲參數,並返回同一個或更新後的響應對象
@app.after_request
def response_logger(response):
# 獲取接口響應數據
api_path = request.full_path
api_method = request.method
ip_addr = request.remote_addr
# 獲取接口請求數據
try:
request_data = request.get_json(force=True)
except Exception as e:
request_data = request.form.to_dict()
request_data, response_data = str(request_data), str(response.json)
with open(logdir.joinpath('runtime.log'), 'a+', encoding="utf-8") as f:
asctime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
f.write(
asctime + " " + ip_addr + " " + api_method + " " + api_path + '->' + request_data + '\n' + response_data + '\n')
# 記錄慢查詢日誌,在日誌處理器函數中會將其寫入到文件中
for query in get_debug_queries():
if query.duration >= app.config['FLASK_SLOW_DB_QUERY_TIME']:
app.logger.warning(
'Slow query: %s\n Parameters: %s\n Duration: %fs\n Context: %s'
% (query.statement, query.parameters, query.duration, query.context))
return response
return app
def register_logger(app):
app.logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 設置日誌文件最大尺寸和備份數量
# 最大尺寸爲10M,當超過10M產生備份文件,最多產生10個備份文件,10個備份文件全部存滿後,會開始覆蓋之前的文件
file_handler = RotatingFileHandler(logdir.joinpath('runtime.log'), maxBytes=10 * 1024 * 1024, backupCount=10)
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.info('Autoline Startup...') # 這裏額外在日誌文件中記錄下每次應用服務的啓動時間
config.py
是項目配置文件,相關內容如下:
class BaseConfig(object):
# 啓用慢查詢記錄功能(調試模式下自動啓用), 爲了在生產環境下可用,必須手動配置此項爲True
SQLALCHEMY_RECORD_QUERIES = True
# 慢查詢閾值
FLASK_SLOW_DB_QUERY_TIME = 0.001
class DevelopmentConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = os.getenv("DB_DEVELOPMENT_URI")
class TestingConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = os.getenv("DB_Testing_URI")
class ProductionConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = os.getenv('DB_PRODUCTION_URI')
config = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig
}
在配置文件中,爲了測試慢查詢日誌記錄,特意將FLASK_SLOW_DB_QUERY_TIME
設置爲0.001s. 在本地開發環境下請求下flask接口,在控制檯可以看到有相關的日誌輸出,如下:
【To Be Continued...】