如何用装饰器模式在不修改原代码前提下增加埋点功能

张开发
2026/4/21 0:52:38 15 分钟阅读

分享文章

如何用装饰器模式在不修改原代码前提下增加埋点功能
functools.wraps是必选项否则原函数的__name__、__doc__、__annotations__丢失导致日志、监控、OpenAPI工具无法识别真实函数埋点需用try-except兜底禁用同步HTTP请求带参装饰器须冻结参数避免闭包污染Annotated仅作类型提示无法替代运行时埋点逻辑。装饰器加埋点时为什么 functools.wraps 不是可选项而是必选项不加 functools.wraps 会导致原函数的 __name__、__doc__、__annotations__ 全部丢失日志、监控系统或 OpenAPI 自动生成工具会拿不到真实函数信息埋点打上去也查不到归属。典型现象logger.info(fcalling {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(categoryapi) 这种带参装饰器时最容易踩的坑是外层函数返回的 wrapper 捕获了循环变量或上层局部变量导致所有被装饰函数共享同一份参数。 幻导航网 发现优质实用网站,开启网络探索之旅

更多文章