Python中如何进行全局的请求日志记录?

现在有多个接口,怎么能够给这些接口添加统一的请求日志记录功能,并且自动在有新增的接口时,也无感增加日志记录?

在网上搜索到的方法都是写一个装饰器,然后在接口函数上使用这个装饰器。这种方法没有满足无感的需求,如果写代码的时候忘记加装饰器的话,就没有日志记录了


Python中如何进行全局的请求日志记录?
16 回复

中间件


在Python中做全局请求日志记录,最直接的方式是用一个装饰器或者中间件来包装你的请求处理函数。如果你用Flask,可以搞个before_requestafter_request钩子;如果用FastAPI或Starlette,就整一个中间件。下面给个Flask和FastAPI的例子。

Flask的例子:

from flask import Flask, request, g
import time
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = Flask(__name__)

@app.before_request
def start_timer():
    g.start_time = time.time()

@app.after_request
def log_request(response):
    if request.path == '/favicon.ico':
        return response
    latency = time.time() - g.start_time
    logger.info(f"{request.method} {request.path} {response.status_code} {latency:.3f}s")
    return response

@app.route('/')
def hello():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

FastAPI的例子:

from fastapi import FastAPI, Request
import time
import logging
from starlette.middleware.base import BaseHTTPMiddleware

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class LoggingMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        start_time = time.time()
        response = await call_next(request)
        latency = time.time() - start_time
        logger.info(f"{request.method} {request.url.path} {response.status_code} {latency:.3f}s")
        return response

app = FastAPI()
app.add_middleware(LoggingMiddleware)

@app.get("/")
async def root():
    return {"message": "Hello World"}

这两个例子都会在每次请求时打印方法、路径、状态码和耗时。用中间件或钩子能确保所有请求都被记录,不用在每个视图函数里单独写日志代码。

简单说就是挂个钩子或中间件来统一记日志。

全部接口继承一个基类

什么框架,flask 可以设置生命周期。其他框架也有的,自己查查文档。也可以自己写个 装饰器。

嗯嗯,除了这种方式,还有其它的方法么?
不用框架有什么方法么?
是指 django 的中间件么?不用框架有什么方法么?

不用框架就只能 monkey patch 了

做一个 metaclass,然后你就可以自动给所有成员函数自动加装饰器了。

赞同楼上 写一个 metaclass 给所有成员函数加上这个装饰器
不过我不觉得直接给接口函数加装饰器有什么问题

没有拦截器?

实在想无感,直接在 nginx 反代层做好了。
思维不要限制在 flask 之内嘛。




感谢,我瞅瞅;接口加装饰器当然没问题,不过我觉得有点烦…

Java 的那个拦截器么?我也想问哈哈哈,看起来是没有的

感谢,虽然一般没有这么做的,但也是个思路~

所有 logger 都输出到 stderr,然后用 supervisor 把输出重定向到一个文件里

如果是接口的请求最好直接在网关层做,微服务里应该很好做,我不喜欢在服务自己的框架里做很多事情,keep it simple

uwsgi 的日志不是记录的都有么?直接日子分析下不就好了?

.before_request

emm…我之前就是写了个装饰器,没想到什么好办法

回到顶部