标准库没有内置 @log 装饰器;工程里通常自定义 logging 装饰器。本文给出可复用模式,并说明与 00.概念-装饰器机制 中 function_timer 的关系。
0. 一句话定位
| 维度 | 内容 |
|---|---|
| 作用对象 | 函数 |
| 使用场景 | 日志 |
| 来源 | 自定义(基于 logging + functools.wraps) |
| 语法形式 | @log_call / @log_exceptions(logger=...) |
1. 做什么
在函数调用前/后写日志:记录函数名、参数(可脱敏)、返回值或异常、耗时;统一格式与 logger 名称,避免业务代码散落 print。
2. 重点参数(以自定义 log_call 为例)
| 参数 | 类型 | 默认值 | 作用 | 配置建议 |
|---|---|---|---|---|
logger |
logging.Logger |
logging.getLogger(__name__) |
输出目标 | 模块级 logger = logging.getLogger(__name__) |
level |
int | logging.INFO |
日志级别 | 调试路径用 DEBUG |
log_args |
bool | True |
是否记录参数 | 生产环境敏感参数设 False |
log_result |
bool | False |
是否记录返回值 | 大对象勿开 |
slow_threshold |
float | None |
超过秒数打 WARNING | 与计时结合 |
3. 最小可运行示例
1 | import logging |
4. 常见变体
带配置的工厂装饰器
1 | def log_call(logger=None, level=logging.INFO): |
仅记录异常
1 | def log_exceptions(logger=None): |
异步版本
1 | def log_call_async(fn): |
类方法注意:装饰实例方法时 args[0] 为 self,日志中可省略或缩短。
5. 适用 / 不适用
适用
- 服务层关键函数、集成调试、慢调用告警
- 统一异常栈记录(配合
logger.exception)
不适用
- 生产高频路径全量
INFO+ 大对象 → 磁盘与性能压力 - 替代专业 APM(OpenTelemetry、Datadog)→ 装饰器可作补充
6. 易踩坑
- 必须
@wraps,否则日志里函数名全是wrapper - 记录密码、token、PII 须脱敏或关闭
log_args logging默认只输出 WARNING+ 到 stderr,需basicConfig或 handler 配置- 多进程/多 worker 各自写文件需
RotatingFileHandler或集中日志 - 与
function_timer重复时合并为一个装饰器,避免双层包装
7. 近邻替代
| 替代 | 何时用 |
|---|---|
标准库 @contextmanager + with |
块级日志 |
| OpenTelemetry span | 分布式追踪 |
FastAPI @app.middleware |
HTTP 请求级访问日志 |
8. 参考
- Python logging 文档
- 装饰器基础见 00.概念-装饰器机制