【FastAPI】日志
一、概述
FastAPI 是一个现代的、快速(高性能)的Web框架,用于构建API,基于Python类型提示。
日志记录是任何应用程序中不可或缺的一部分,它允许开发者追踪事件的发生、识别错误并了解系统的运行状态。
在 FastAPI 中,日志配置可以通过多种方式进行,包括直接使用 Python 的标准 logging 模块、集成第三方库如 loguru,以及通过 uvicorn 的日志配置来实现。
二、实现方法
2.1 使用 Python 标准 logging 模块
FastAPI 默认集成了 Python 的标准logging
模块,这使得我们可以很容易地配置和管理应用程序的日志输出。
要将日志信息输出到文件中,可以使用 RotatingFileHandler
来创建一个日志处理器实例,并将其添加到 logger 中。
例如:这段代码将所有 INFO 级别及以上的日志消息记录到 app.log
文件中,当文件大小超过 1MB
时会自动创建新的备份文件。
import logging
from logging.handlers import RotatingFileHandler
from fastapi import FastAPI
# 初始化 FastAPI 应用
app = FastAPI()
# 创建 RotatingFileHandler 实例
file_handler = RotatingFileHandler(
filename="app.log", maxBytes=1000000, backupCount=10)
# 设置日志格式
formatter = logging.Formatter(
"%(asctime)s - %(levelname)s - %(message)s")
file_handler.setFormatter(formatter)
# 获取根 logger 并添加 handler 和级别
logger = logging.getLogger()
logger.addHandler(file_handler)
logger.setLevel(logging.INFO)
@app.get("/")
async def read_root():
logger.info("访问了根路径")
return {"Hello": "World"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
2.1 使用 Loguru 库
尽管 Python 的 logging 模块功能强大,但它的配置可能相对复杂。
Loguru 提供了一个更简洁的接口,简化了日志记录的过程。
通过 pip 安装 ·loguru· 后,可以在 FastAPI 项目中轻松集成它,以获得更加用户友好的日志记录体验。
例如:这里展示了如何配置 loguru 来记录日志到文件,并且设置了每日轮换和最多保留一天的日志文件。
from loguru import logger
from fastapi import FastAPI
app = FastAPI()
log_path = '/u01'
if not os.path.exists(log_path):
os.mkdir(log_path)
log_file = '{0}/fa_25_{1}_log.log'.format(log_path, datetime.now().strftime('%Y-%m-%d'))
logger.add(log_file, rotation="12:00", retention="1 days", enqueue=True)
@app.get("/")
async def root():
logger.info('Hello world')
logger.info('日志测试。')
return "Hello world"
2.3 配置 Uvicorn 日志
Uvicorn 是一个用于运行 ASGI 应用程序的服务器,通常用来启动 FastAPI 应用。
Uvicorn 自身也支持日志配置,可以通过传递 log_config 参数给 uvicorn.run() 方法来自定义日志格式和行为。
例如:这段 JSON 配置定义了日志的格式化方式,其中包括时间戳、线程名称等信息,并指定了日志应该被发送到的标准输出流或文件。
在这个例子中,我们指定了一个外部的日志配置文件 path/to/logconfig.json,其中包含了详细的日志格式化规则和处理器配置6。这使得我们可以灵活地调整日志输出的行为,而无需修改应用程序本身的代码。
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"default": {
"()": "uvicorn.logging.DefaultFormatter",
"fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(message)s",
"use_colors": null
},
"access": {
"()": "uvicorn.logging.AccessFormatter",
"fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(client_addr)s - '%(request_line)s' %(status_code)s"
}
},
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stderr"
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout"
}
},
"loggers": {
"fastapi": {
"handlers": ["default"],
"level": "INFO"
},
"uvicorn": {
"handlers": ["default"],
"level": "INFO"
},
"uvicorn.error": {
"level": "INFO"
},
"uvicorn.access": {
"handlers": ["access"],
"level": "INFO",
"propagate": false
}
}
}
然后,在启动应用时可以这样调用:
import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000, log_config='path/to/logconfig.json')
三、FastAPI的日志级别
FastAPI 应用的日志级别可以通过多种方式来配置,这取决于你是想调整整个应用的日志输出,还是仅针对特定部分。
日志级别是用于指示事件重要性的标签,它们帮助开发者决定哪些信息应该被记录下来以供后续分析或调试。
通常情况下,Python 的 logging 模块提供了以下几种日志级别(按照严重性递增):
DEBUG (10)
:详细的调试信息,通常只在诊断问题时有用。INFO (20)
:确认程序按预期工作,表示应用程序正常运行的信息。WARNING (30)
:表示某些非致命问题的警告信息,但这些问题可能需要关注。ERROR (40)
:由于更严重的问题导致功能未能执行的日志信息。CRITICAL (50)
:非常严重的错误,表明程序本身可能无法继续运行。
在 FastAPI 中,你可以通过 Python 标准库中的 logging 模块来设置日志级别,或者使用 Uvicorn 提供的命令行选项和配置文件来控制日志输出的行为。
下面将详细介绍如何为 FastAPI 设置不同的日志级别。
- 使用 Python 标准 logging 模块设置日志级别
当你使用 Python 的标准 logging 模块时,可以创建一个 logger 对象,并通过 setLevel() 方法来指定最低的日志级别。
任何低于该级别的消息都将被忽略。
例如,如果你设置了 INFO 级别,则只有 INFO、WARNING、ERROR 和 CRITICAL 级别的消息会被记录下来。
在这个例子中,尽管我们调用了 logger.debug(),但由于日志级别设置为 INFO,所以这条消息不会出现在输出中。
import logging
from fastapi import FastAPI
app = FastAPI()
# 创建并配置 logger
logger = logging.getLogger()
logger.setLevel(logging.INFO) # 设置全局日志级别为 INFO
@app.get("/")
async def read_root():
logger.debug("这是一个调试信息") # 不会打印,因为低于 INFO 级别
logger.info("访问了根路径")
return {"Hello": "World"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
- 使用 Uvicorn 设置日志级别
Uvicorn 是 FastAPI 的 ASGI 服务器实现之一,它允许你通过命令行参数或配置文件来设置日志级别。你可以直接在启动命令中添加 --log-level 参数来改变日志级别,如 uvicorn main:app --log-level debug。此外,还可以通过 JSON 或 YAML 格式的日志配置文件来进一步自定义日志格式和其他行为1。
例如,创建一个名为 uvicorn_config.json 的日志配置文件:
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"default": {
"()": "uvicorn.logging.DefaultFormatter",
"fmt": "%(asctime)s %(levelprefix)s %(message)s",
"use_colors": null
},
"access": {
"()": "uvicorn.logging.AccessFormatter",
"fmt": "%(asctime)s %(levelprefix)s %(client_addr)s - '%(request_line)s' %(status_code)s"
}
},
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stderr"
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout"
}
},
"loggers": {
"fastapi": {
"handlers": ["default"],
"level": "DEBUG" # 设置 FastAPI 日志级别为 DEBUG
},
"uvicorn": {
"handlers": ["default"],
"level": "INFO"
},
"uvicorn.error": {
"level": "INFO"
},
"uvicorn.access": {
"handlers": ["access"],
"level": "INFO",
"propagate": false
}
}
}
然后,在启动应用时可以这样调用:
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000, log_config='path/to/uvicorn_config.json')
在这个配置文件中,我们将 FastAPI 的日志级别设置为了 DEBUG,这意味着所有级别的日志都会被记录下来。
请注意,这里提到的 fastapi logger 并不是默认存在的;
你需要确保你的应用程序中有相应的 logger 被正确命名并使用。
四、相关链接
【FastAPI】日志
【FastAPI】中间件
【FastAPI】简介
【FastAPI】BaseModel类