fastapi uvicorn配置日志
目前从flask框架转fastapi,之前flask框架日志很好用。这次学习了fastapi的日志使用,第一种是自定义日志,这个不讲了,自己封装就好,第二种是使用uvicorn自带日志。
一、配置输出格式化
uvicorn 其实已经有日志,只是没有格式化输出,我们希望可以加点东西丰富输出。
找到 uvicorn.config 里的源码, LOGGING_CONFIG配置如下:
LOGGING_CONFIG: Dict[str, Any] = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"default": {
"()": "uvicorn.logging.DefaultFormatter",
"fmt": "%(levelprefix)s %(message)s",
"use_colors": None,
},
"access": {
"()": "uvicorn.logging.AccessFormatter",
"fmt": '%(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s', # noqa: E501
},
},
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stderr",
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout",
},
},
"loggers": {
"uvicorn": {"handlers": ["default"], "level": "INFO", "propagate": False},
"uvicorn.error": {"level": "INFO"},
"uvicorn.access": {"handlers": ["access"], "level": "INFO", "propagate": False},
},
}
这段默认配置我们可以自定义,不过不是改源码,是初始化时加载我们新建的配置。比如在用 uvicorn 启动时,加上参数 log_config,uvicorn 自定义日志配置文件支持 json、yaml、ini 三种格式。
uvicorn.run(app='main:app',host="0.0.0.0",log_config='./uvicorn_config.json',port=8000,loop="asyncio")
以下这段 json 实现了,格式化输出控制台,日志输出到本地文件。首先创建 uvicorn_config.json 存放项目根目录:
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"default": {
"()": "uvicorn.logging.DefaultFormatter",
"fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(message)s", # 增加了asctime和threadName
"use_colors": null
},
"access": {
"()": "uvicorn.logging.AccessFormatter",
"fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(client_addr)s - '%(request_line)s' %(status_code)s" # 增加了asctime和threadName
}
},
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stderr"
},
# default日志输出到本地文件,定义了日志路径、备份数量
"default_file": {
"formatter": "default",
"class": "logging.handlers.TimedRotatingFileHandler",
"filename": "./logs/app.log",
"when": "midnight",
"encoding": "utf-8",
"backupCount": 10
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout"
},
# access日志输出到本地文件,定义了日志路径、备份数量
"access_file": {
"formatter": "access",
"class": "logging.handlers.TimedRotatingFileHandler",
"filename": "./logs/app.log",
"when": "midnight",
"encoding": "utf-8",
"backupCount": 10
}
},
"loggers": {
# 添加handler,default_file
"uvicorn": {"handlers": ["default","default_file"], "level": "INFO", "propagate": false},
"uvicorn.error": {"level": "INFO"},
# 添加handler,access_file
"uvicorn.access": {"handlers": ["access","access_file"], "level": "INFO", "propagate": false}
}
}
main.py文件
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/home")
async def get():
return {'message':'OK'}
@app.get("/test")
async def get():
return {'message':'OK'}
@app.get("/dev")
async def get():
return {'message':'OK'}
if __name__ == "__main__":
# log_config 加载日志配置
uvicorn.run(app='main:app',host="0.0.0.0",log_config='./uvicorn_config.json',port=8000,loop="asyncio")
运行main.py
控制台
app.log
二、业务代码调用 uvicorn 日志
查看 uvicorn 日志源码处理机制发现,本质上还是 logger.addHandler 方法添加 handler,所以可以用以下方法调用:
from fastapi import FastAPI
import uvicorn,logging
app = FastAPI()
log = logging.getLogger("uvicorn")
@app.get("/home")
async def get():
log.info('this is a test')
return {'message':'OK'}
@app.get("/test")
async def get():
return {'message':'OK'}
@app.get("/dev")
async def get():
return {'message':'OK'}
if __name__ == "__main__":
# log_config 加载日志配置
uvicorn.run(app='main:app',host="0.0.0.0",log_config='./uvicorn_config.json',port=8000,loop="asyncio")
输出: