fastapi: 第十四章: loguru记录多个日志

一,应用场景:

生产环境中,有时需要明确告诉loguru,我要把日志写入到定义的哪个文件中。
例如:有一个日志记录支付宝post的数据,有另一个日志记录快递100提交的数据

怎么做?

loguru 中,明确指定某条日志写入哪个文件的标准做法是:使用 logger.bind(name="特定标识")
配合在 logger.add() 中设置对应的 filter
这相当于给不同的日志文件拉了“专属微信群”,
你用 bind 给日志打上标签,它就会自动对号入座,绝对不会串门

二,代码:

说明:

  • logger.bind(key=value):它的作用是在日志的 extra 字典中注入一对键值对。
  • record["extra"].get("log_type") == "alipay"loguru 每记录一条日志,都会把日志送到所有 add 的文件里过一遍筛选。
    过滤器发现这条日志的 extra 里恰好有 log_type="alipay"alipay.log 就会收下它;
    kuaidi100.log 发现不匹配,就会直接忽略它。
通过这种“打标签-对暗号”的方式,你可以在项目里精准控制任何一条日志的去向。

配置logger

# app/core/logger.py
import os
import sys
from loguru import logger

# 确定日志存放目录
LOG_DIR = os.path.join(os.getcwd(), "logs")
os.makedirs(LOG_DIR, exist_ok=True)

# 1. 清除 Loguru 默认的控制台处理器
logger.remove()

# 2. 添加带颜色的控制台输出(开发环境)
logger.add(
    sys.stdout,
    level="INFO",
    format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
)

# 3. 添加文件输出(生产环境,按天轮转,通用)
logger.add(
    os.path.join(LOG_DIR, "app_{time:YYYY-MM-DD}.log"),
    # 核心:只有调用 logger.bind(log_type="alipay") 的日志才会写入此文件
    filter=lambda record: record["extra"].get("log_type") == "system",
    level="INFO",
    rotation="00:00",    # 每天午夜 0 点创建新日志
    retention="30 days", # 日志保留 30 天
    compression="zip",   # 历史日志自动压缩为 zip
    enqueue=True,        # 开启异步/线程安全写入
    format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {name}:{function}:{line} - {message}",
)

# 4. 支付宝专用日志文件
logger.add(
    os.path.join(LOG_DIR, "alipay_{time:YYYY-MM-DD}.log"),
    level="INFO",
    # 核心:只有调用 logger.bind(log_type="alipay") 的日志才会写入此文件
    filter=lambda record: record["extra"].get("log_type") == "alipay",
    format="{time:YYYY-MM-DD HH:mm:ss} | {message}",
    encoding="utf-8",
    enqueue=True,
    rotation = "00:00",  # 每天午夜 0 点创建新日志
    retention = "30 days",  # 日志保留 30 天
)

# 5. 快递100专用日志文件
logger.add(
    os.path.join(LOG_DIR, "kuaidi100_{time:YYYY-MM-DD}.log"),
    level="INFO",
    # 核心:只有调用 logger.bind(log_type="kuaidi100") 的日志才会写入此文件
    filter=lambda record: record["extra"].get("log_type") == "kuaidi100",
    format="{time:YYYY-MM-DD HH:mm:ss} | {message}",
    encoding="utf-8",
    enqueue=True,
    rotation="00:00",  # 每天午夜 0 点创建新日志
    retention="30 days",  # 日志保留 30 天
)

# 导出配置好的 logger
__all__ = ["logger"]

业务中调用logger

# app/api/users.py
from fastapi import APIRouter
from app.core.logger import logger

# 创建路由器实例
# prefix:所有路由的统一前缀,避免重复写"/users"
# tags:在Swagger文档中分组显示
router = APIRouter(prefix="/users", tags=["用户管理"])

@router.get("/all")
def get_all_users():
    """获取所有用户"""
    log_alipay = "支付宝post数据"
    logger.bind(log_type="alipay").info(f"收到支付宝推送: {log_alipay}")

    log_kuaidi100 = "快递100post数据"
    logger.bind(log_type="kuaidi100").info(f"收到快递100推送: {log_kuaidi100}")

    return [{"id": 1, "name": "张三"}, {"id": 2, "name": "李四"}]

异常时调用logger

    # 4. 捕获系统未知异常 (如: 代码崩溃、数据库连接断开 500)
    @app.exception_handler(Exception)
    async def all_exception_handler(request: Request, exc: Exception):
        # 注意:生产环境应将 exc 记录到日志系统(如 loguru)
        params = await get_query_param(request)
        logger.bind(log_type="system").exception(f"服务器内部崩溃 -> {params}")
        content = BaseResponse(code=500, msg="服务器内部错误,请稍后再试", data=None).model_dump()
        return JSONResponse(status_code=500, content=content)

三,查看效果:

kuaidi100的回调数据的log

2026-05-24 14:53:43 | 收到快递100推送: 快递100post数据

 

posted @ 2026-06-10 15:20  刘宏缔的架构森林  阅读(8)  评论(0)    收藏  举报