如何修改Flask中指定路由/ready的日志级别
问题:Flask中如何仅让/ready路径的请求日志只在DEBUG级别记录?
我的Flask应用代码如下:
from flask import Flask, render_template, jsonify import os app = Flask(__name__) import logging LOGLEVEL = os.environ.get("LOGLEVEL", "INFO").upper() logging.basicConfig(level=LOGLEVEL) logger = logging.getLogger() @app.route("/") def splash(): response = jsonify(success=True) return response @app.route("/ready") def ready(): response = jsonify(success=True) return response if __name__ == "__main__": port = int(os.environ.get("PORT", 80)) host = "0.0.0.0" app.run(host=host, port=port, debug=False, use_reloader=False)
当前设置INFO日志级别时,/ready的请求会被记录为:
INFO:werkzeug:10.123.123.123 - - [18/Oct/2022 19:32:45] "GET /ready HTTP/1.1" 200 -
我想要实现的是:仅修改/ready路径的日志级别,让它不在INFO级别记录响应,只有在DEBUG级别才会输出该请求的日志。
我尝试过以下两种方法,但都没有效果:
方法一:
@app.route("/ready") def ready(): route_logger = app.logger route_logger.setLevel(logging.DEBUG) response = jsonify(success=True) return response
方法二:
logging.getLogger("mymodule.ready").setLevel(logging.DEBUG)
解决方案
问题核心在于:你看到的请求日志是由werkzeug日志器输出的,而非app.logger或自定义的mymodule.ready日志器,所以之前修改的对象完全不对。
下面提供两种可行的实现方式:
方案1:自定义过滤器过滤werkzeug日志
创建一个日志过滤器,检查日志消息是否包含/ready路径,仅当全局日志级别为DEBUG时才允许输出该路径的请求日志:
from flask import Flask, jsonify import os import logging from logging import Filter class ReadyRouteFilter(Filter): def filter(self, record): # 只针对werkzeug的日志消息做过滤 if record.name == 'werkzeug' and '/ready' in record.getMessage(): # 只有当全局日志级别<=DEBUG时,才输出该日志 return logging.getLogger().getEffectiveLevel() <= logging.DEBUG # 其他日志正常输出 return True app = Flask(__name__) LOGLEVEL = os.environ.get("LOGLEVEL", "INFO").upper() logging.basicConfig(level=LOGLEVEL) logger = logging.getLogger() # 给werkzeug日志器添加自定义过滤器 werkzeug_logger = logging.getLogger('werkzeug') werkzeug_logger.addFilter(ReadyRouteFilter()) @app.route("/") def splash(): response = jsonify(success=True) return response @app.route("/ready") def ready(): response = jsonify(success=True) return response if __name__ == "__main__": port = int(os.environ.get("PORT", 80)) host = "0.0.0.0" app.run(host=host, port=port, debug=False, use_reloader=False)
方案2:利用请求钩子动态切换日志级别
通过Flask的before_request和after_request钩子,在/ready请求进入时临时提高werkzeug的日志级别(让INFO级别的日志被过滤),请求结束后恢复原级别:
from flask import Flask, jsonify, request import os import logging app = Flask(__name__) LOGLEVEL = os.environ.get("LOGLEVEL", "INFO").upper() logging.basicConfig(level=LOGLEVEL) logger = logging.getLogger() werkzeug_logger = logging.getLogger('werkzeug') # 保存werkzeug的原始日志级别 original_werkzeug_level = werkzeug_logger.level @app.before_request def adjust_log_level(): if request.path == '/ready': # 临时将werkzeug日志级别设为DEBUG,这样INFO级别的请求日志会被过滤 werkzeug_logger.setLevel(logging.DEBUG) @app.after_request def restore_log_level(response): if request.path == '/ready': # 请求结束后恢复原始级别 werkzeug_logger.setLevel(original_werkzeug_level) return response @app.route("/") def splash(): response = jsonify(success=True) return response @app.route("/ready") def ready(): response = jsonify(success=True) return response if __name__ == "__main__": port = int(os.environ.get("PORT", 80)) host = "0.0.0.0" app.run(host=host, port=port, debug=False, use_reloader=False)
方案对比
- 方案1更可靠,直接针对日志内容过滤,不会受并发请求影响;
- 方案2需要注意请求前后的级别恢复,多线程/多进程部署时可能存在级别混乱风险。
内容的提问来源于stack exchange,提问作者red888
相关产品推荐
相关产品推荐

