You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Prometheus Client与FastAPI函数双重装饰器失效问题求助

问题解决:FastAPI路由装饰器与Prometheus指标装饰器共存方案

核心问题原因

你的代码失效主要源于两点:

  1. Prometheus Client的Gauge.time()装饰器默认仅支持同步函数,而你的FastAPI接口是异步(async def)类型,未指定异步支持参数导致装饰器无法正确工作。
  2. 装饰器顺序搭配错误,FastAPI路由装饰器需要作为最外层装饰器,确保路由系统能正确识别并注册处理函数。

正确实现代码

from fastapi import APIRouter, Request
from prometheus_client import Gauge

rest_app = APIRouter(prefix='/rest')
TIME_METRICS_ANNOTATION = Gauge('request_time_taken', 'Time Taken for My Endpoint')

@rest_app.post("/endpoint")
@TIME_METRICS_ANNOTATION.time(async=True)  # 关键:添加async=True支持异步函数
async def my_endpoint(request: Request):
    # 你的业务逻辑代码
    return {"result": "success"}

关键说明

  • 装饰器顺序:FastAPI路由装饰器(@rest_app.post)必须放在最外层,它的作用是将内层装饰后的异步函数注册为接口路由;Prometheus的计时装饰器放在内层,直接作用于实际处理请求的函数。
  • async=True参数:告知Prometheus装饰器当前处理的是异步函数,会自动适配异步上下文的时间捕获逻辑。

附带疑问解答:Counter类型的装饰器实现

Prometheus Client的Counter确实没有内置的装饰器(不像Gauge/Summary提供time()),但可以通过functools.wraps快速实现一个请求计数装饰器:

异步函数版本

from prometheus_client import Counter
from functools import wraps
from fastapi import APIRouter, Request

rest_app = APIRouter(prefix='/rest')
REQUEST_COUNT = Counter('request_count', 'Total requests to /rest/endpoint')

def count_requests(func):
    @wraps(func)
    async def wrapper(*args, **kwargs):
        REQUEST_COUNT.inc()  # 每次请求递增计数
        return await func(*args, **kwargs)
    return wrapper

# 使用示例
@rest_app.post("/endpoint")
@count_requests
@TIME_METRICS_ANNOTATION.time(async=True)
async def my_endpoint(request: Request):
    # 业务逻辑
    return {"result": "success"}

同步函数版本(如果需要)

def count_requests_sync(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        REQUEST_COUNT.inc()
        return func(*args, **kwargs)
    return wrapper

内容的提问来源于stack exchange,提问作者Sree Karthik S R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 08:43:13