
本文详解如何绕过 Loguru 默认的冗余 JSON 序列化逻辑,通过自定义 serialize 处理器与 format 字符串,实现完全可控的轻量级 JSON 日志输出(如仅保留 time 和 error 字段),适配 FastAPI 等生产环境。
本文详解如何绕过 loguru 默认的冗余 json 序列化逻辑,通过自定义 `serialize` 处理器与 `format` 字符串,实现完全可控的轻量级 json 日志输出(如仅保留 `time` 和 `error` 字段),适配 fastapi 等生产环境。
Loguru 默认的 JSON 序列化(如 _serialize_record)会嵌套大量字段(process、thread、file、extra 等),而实际业务中常需极简结构——例如仅输出 {"time": "5:30pm", "error": "Type error"}。关键在于:不能修改内部私有方法,而应通过 add() 的 serialize + format 组合实现完全定制。
✅ 正确做法:使用 serialize=True + 自定义 format + 手动序列化
Loguru 提供了 serialize=True 参数,它会将 record 交由你控制的 format 字符串处理;此时 format 不再是纯字符串模板,而是可执行的函数(返回字符串),我们可在其中构造任意 JSON 结构:
import json
from datetime import datetime
from loguru import logger
def custom_json_format(record):
# 提取并格式化时间(如 "5:30pm")
time_obj = record["time"]
formatted_time = time_obj.strftime("%I:%M%p").lower() # → "5:30pm"
# 提取错误信息(仅当存在异常时)
error_msg = ""
if record["exception"]:
exc = record["exception"]
error_msg = f"{exc.type.__name__}: {exc.value}"
# 构建最小化 JSON 对象
data = {
"time": formatted_time,
"error": error_msg or record["message"],
}
return json.dumps(data, ensure_ascii=False) + "\n"
# 移除默认处理器,添加自定义 JSON 输出
logger.remove()
logger.add(
"app.log",
format=custom_json_format, # ← 关键:传入函数而非字符串
serialize=True, # ← 启用 record 传递模式
level="INFO",
rotation="10 MB"
)
# 测试
logger.info("正常日志")
logger.error("发生类型错误") # 无异常堆栈时
try:
1 / 0
except Exception:
logger.exception("捕获到异常") # 此时 error 字段含异常类型+消息
⚠️ 注意事项与最佳实践
- serialize=True 是开关:它让 Loguru 将 record 作为参数传给 format 函数,否则 format 仅支持 {time} {message} 等占位符,无法访问原始异常对象。
- 避免重写 _serialize_record:该方法为私有静态方法,非公开 API,强行 monkey patch 易导致版本升级后崩溃。
- FastAPI 集成建议:在应用启动时配置 logger(如 main.py 中 configure_logger()),并通过 logger.bind(request_id=...).info(...) 添加上下文字段,并在 custom_json_format 中从 record["extra"] 提取。
- 性能提示:若高频日志,可预编译 json.dumps 或使用 orjson 替代标准库以提升序列化速度。
✅ 总结
Loguru 的灵活性在于“解耦格式化与序列化”:format 控制内容结构,serialize=True 提供数据源,json.dumps 执行最终输出。无需侵入源码,即可精准输出符合 SRE 规范或 ELK 入口要求的扁平化 JSON 日志——这才是生产级日志定制的正确路径。











