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

如何包装coroutine.__await__()?实现asyncpg连接池准确日志统计

解决asyncpg连接池获取/释放统计的时机问题

直接在__await__方法中提前更新计数器,会把「发起连接获取请求」误判为「连接获取成功」,必须等连接实际拿到手后再更新统计。以下是两种可行的解决方案:

方案1:包装__await__生成器,确保成功获取后计数

如果你的代码是通过实现__await__来包装连接获取逻辑,可以修改成如下方式:通过包装原生成器,等待异步流程完成(拿到连接)后再更新统计:

class PoolWrapper:
    def __init__(self, pool):
        self.pool = pool
        self.acquire_success_count = 0
        self.release_count = 0

    def __await__(self):
        # 获取原连接获取操作的生成器
        acquire_gen = self.pool.acquire().__await__()
        try:
            # 完成整个异步获取流程,拿到连接对象
            conn = yield from acquire_gen
            # 只有成功拿到连接才更新计数
            self.acquire_success_count += 1
            return conn
        except Exception:
            # 获取失败时不统计,直接抛出异常
            raise

注意这种方式只处理了获取统计,释放操作需要手动在调用pool.release(conn)时更新计数器:

await self.pool.release(conn)
self.release_count += 1

方案2:用异步上下文管理器完整统计获取/释放

更稳妥的方式是实现一个异步上下文管理器,把获取和释放的统计逻辑封装在一起,确保统计的对应性:

class PoolStatsTracker:
    def __init__(self, pool):
        self.pool = pool
        self.acquire_success_count = 0
        self.release_count = 0
        self._connection = None

    async def __aenter__(self):
        # 等待连接实际获取成功后再计数
        self._connection = await self.pool.acquire()
        self.acquire_success_count += 1
        return self._connection

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        # 确保连接释放完成后再统计释放次数
        await self.pool.release(self._connection)
        self.release_count += 1
        # 可选:如果需要统计获取失败次数,可在__aenter__的异常分支中添加逻辑

使用时和原生连接池的async with语法完全一致:

async with PoolStatsTracker(your_pool) as conn:
    # 执行数据库操作,比如 await conn.fetch('SELECT * FROM your_table')

原实现的问题根源

原来的__await__方法在被调用时就直接更新了计数器,但此时__await__返回的只是一个异步生成器,连接获取的异步流程还没完成——只有当生成器迭代结束、拿到连接对象时,才代表连接真正获取成功。提前更新计数器会导致统计数据包含「发起但未成功的获取请求」,进而失真。

内容的提问来源于stack exchange,提问作者Ivan Bond

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 22:32:48