如何用装饰器模式在不修改原代码前提下增加埋点功能
functools.wraps是必选项,否则原函数的__name__、__doc__、__annotations__丢失,导致日志、监控、OpenAPI工具无法识别真实函数;埋点需用try-except兜底,禁用同步HTTP请求;带参装饰器须冻结参数避免闭包污染;Annotated仅作类型提示,无法替代运行时埋点逻辑。装饰器加埋点时,为什么 functools.wraps 不是可选项而是必选项不加 functools.wraps 会导致原函数的 __name__、__doc__、__annotations__ 全部丢失,日志、监控系统或 OpenAPI 自动生成工具会拿不到真实函数信息,埋点打上去也查不到归属。典型现象:logger.info(f"calling {func.__name__}") 打出的是 "wrapper" 而不是真实函数名调试时 help(my_func) 显示空文档,IDE 自动补全失效FastAPI/Flask 的路由注册可能失败,因为框架依赖 __name__ 做唯一标识必须写成:@functools.wraps(func),不能只导入不调用埋点装饰器里怎么安全处理异常,避免拖垮主逻辑埋点本身是旁路行为,一旦出错(比如网络超时、JSON 序列化失败)绝对不能让原函数跟着抛异常或卡住。所有埋点逻辑必须包在 try...except Exception: 里,且 except 中不做 raise别用 logging.exception,它会打完整 traceback,高频调用下 I/O 压力大;改用 logging.debug + 简短错误描述异步场景下禁用同步 HTTP 请求埋点;可用 asyncio.create_task 发 fire-and-forget 请求,但要设 timeout示例关键行:try: send_to_monitoring(...); except Exception as e: logger.debug("track failed: %s", type(e).__name__)带参数的埋点装饰器怎么避免闭包变量污染写成 @track(category="api") 这种带参装饰器时,最容易踩的坑是外层函数返回的 wrapper 捕获了循环变量或上层局部变量,导致所有被装饰函数共享同一份参数。 幻导航网 发现优质实用网站,开启网络探索之旅!
更多推荐
所有评论(0)