loguru默认配置不能直接用于生产环境,因其仅输出日志到stderr、无文件轮转、无结构化字段、不区分环境级别,易导致oom、日志截断或解析失败;需配置rotation、serialize=true、json格式、多进程安全及动态级别调整。

Loguru 的基本配置为什么不能直接用于生产环境
Loguru 默认的 logger 实例会把日志输出到 stderr,不带文件轮转、无结构化字段、不区分环境级别——这在生产环境里等于裸奔。尤其当服务长期运行时,logger.add(sys.stderr) 会持续占用终端句柄,容器环境下还可能因日志量过大触发 OOM 或被日志驱动截断。
真正需要的是:按时间/大小自动轮转 + JSON 格式输出 + 错误日志单独归档 + 级别过滤不干扰监控系统采集。
- 避免用
logger.remove()后只加一个logger.add(...),这会丢失默认 handler,但没补上生产必需能力 - 不要在代码里硬编码路径如
/var/log/myapp.log,应通过环境变量注入,比如os.getenv("LOG_DIR", "/tmp") -
rotation参数别写成"10 MB"就完事——大流量服务下,单文件 10MB 可能几分钟就滚满,建议搭配compression="zip"防止磁盘爆掉
如何让 Loguru 输出结构化 JSON 并兼容 Prometheus 或 ELK
监控系统(比如 Filebeat 或 Prometheus Pushgateway)依赖字段可解析。Loguru 本身不原生支持 JSON 输出,但可通过 serialize=True + 自定义 format 实现,关键是确保 timestamp、level、message、extra 字段稳定存在。
常见错误是只设 serialize=True,结果日志变成一整块 base64 编码字符串,下游根本没法 parse。
- 必须配合
format参数显式控制字段顺序和类型,例如:"{{time}} {{level}} {{message}} {extra}"不行,要写成'{{time:YYYY-MM-DD HH:mm:ss.SSS}} {{level}} {{message}} {extra}' - 用
logger.configure(patcher=lambda record: record["extra"].update({"service": "api", "env": os.getenv("ENV", "dev")}))注入固定上下文,避免每条日志手动传extra - 如果对接 Loki,记得加
enqueue=True避免高并发下日志丢失;但注意它会额外吃内存,需配diagnose=False关闭 traceback 彩色渲染
多进程场景下 Loguru 文件写入冲突怎么破
Loguru 默认不是多进程安全的——当多个 gunicorn worker 或 multiprocessing 子进程同时往同一个文件写日志时,会出现内容错乱、覆盖甚至文件锁死。这不是 bug,是设计使然:Loguru 假设你用 enqueue=True + 外部队列做协调,或干脆交给 systemd/journald 管理。
- 别尝试用
filelock或flock手动加锁,Loguru 的 sink 机制不兼容这类同步原语 - 正确做法是:每个进程写独立文件,靠
rotation+retention控制生命周期,再由日志收集器(如 fluent-bit)统一读取,例如:logger.add(f"{log_dir}/app-{os.getpid()}.log", rotation="100 MB") - 如果非要用共享文件(比如调试阶段),必须启用
enqueue=True,且确保所有进程共用同一个queue对象——但这要求主进程提前创建并传入子进程,gunicorn 下几乎不可行
如何动态调整日志级别而不重启服务
生产环境不可能每次调等级都发版重启。Loguru 支持运行时修改,但要注意:只改 logger.level() 不影响已添加的 handler,必须重新 add 或 patch 已有 handler。
最稳妥的方式是封装一个 reload 接口,比如暴露 HTTP endpoint 或响应 SIGUSR2 信号。
- 用
logger.remove(handler_id)清掉旧 handler,再用新 level 重 add,handler_id 记录在全局变量里 - 别依赖
logger.level("DEBUG")全局生效——它只影响后续新 log 记录,已有 handler 的 filter 逻辑不变 - 如果用了
filter函数做过滤(比如只让 error 进文件),改 level 后必须同步更新该函数返回值,否则出现“日志级别调低了但文件里还是只有 error”这种现象
backtrace 和 diagnose 在生产环境必须关掉。它们会把完整 traceback 转成字符串并格式化,既拖慢性能,又污染 JSON 结构——尤其当异常嵌套深时,单条日志能到 2MB。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











