為 FastAPI 配置日志的三種方法
你好,我是 somenzz,可以叫我征哥,最近在用 FastAPI 的時(shí)候,發(fā)現(xiàn) FastAPI 的官方文檔沒(méi)有配置日志的相關(guān)說(shuō)明,今天就分享一下 FastAPI 配置日志的三種方法。
第一種,就像寫腳本那樣記錄日志
這一種方法最簡(jiǎn)單直接,平時(shí)寫腳本的時(shí)候怎么記錄日志,這里就怎么記錄日志,通常就是先配置日志格式,然后在需要的地方 logger.info 一下:
配置日志:
import?logging
logger?=?logging.getLogger()
logger.setLevel(logging.INFO)
ch?=?logging.StreamHandler()
fh?=?logging.FileHandler(filename='./server.log')
formatter?=?logging.Formatter(
????"%(asctime)s?-?%(module)s?-?%(funcName)s?-?line:%(lineno)d?-?%(levelname)s?-?%(message)s"
)
ch.setFormatter(formatter)
fh.setFormatter(formatter)
logger.addHandler(ch)?#將日志輸出至屏幕
logger.addHandler(fh)?#將日志輸出至文件
如果怕文件太大,可以使用循環(huán)日志:
fh?=?logging.handlers.RotatingFileHandler("api.log",mode="a",maxBytes?=?100*1024,?backupCount?=?3)
然后,在需要記錄日志的地方添加 logger.info / logger.warning / logger.debug / logger.error
from?fastapi?import?FastAPI
#?setup?loggers
import?logging
logger?=?logging.getLogger()
logger.setLevel(logging.INFO)
ch?=?logging.StreamHandler()
fh?=?logging.FileHandler(filename='./server.log'))
ch.setFormatter(LogFormatter())
fh.setFormatter(LogFormatter())
logger.addHandler(ch)?#將日志輸出至屏幕
logger.addHandler(fh)?#將日志輸出至文件
app?=?FastAPI()
@app.get("/")
async?def?root():
????logger.info("logging?from?the?root?logger")
????return?{"status":?"alive"}
你可能會(huì)說(shuō),我接口特別多,難道一行一行加?
那也不用,你可以在中間件里面攔截所有請(qǐng)求,然后日志記錄每一個(gè)請(qǐng)求,完整代碼如下所示:
文件名 main.py,重點(diǎn)在 log_requests 函數(shù):
import?logging
from?fastapi?import?FastAPI
import?time
import?random
import?string
logger?=?logging.getLogger()
logger.setLevel(logging.INFO)
ch?=?logging.StreamHandler()
fh?=?logging.FileHandler(filename='./server.log')
formatter?=?logging.Formatter(
????"%(asctime)s?-?%(module)s?-?%(funcName)s?-?line:%(lineno)d?-?%(levelname)s?-?%(message)s"
)
ch.setFormatter(formatter)
fh.setFormatter(formatter)
logger.addHandler(ch)?#將日志輸出至屏幕
logger.addHandler(fh)?#將日志輸出至文件
logger?=?logging.getLogger(__name__)
app?=?FastAPI()
@app.middleware("http")
async?def?log_requests(request,?call_next):
????idem?=?''.join(random.choices(string.ascii_uppercase?+?string.digits,?k=6))
????logger.info(f"rid={idem}?start?request?path={request.url.path}")
????start_time?=?time.time()
????
????response?=?await?call_next(request)
????
????process_time?=?(time.time()?-?start_time)?*?1000
????formatted_process_time?=?'{0:.2f}'.format(process_time)
????logger.info(f"rid={idem}?completed_in={formatted_process_time}ms?status_code={response.status_code}")
????
????return?response
@app.get("/")
async?def?root():
????return?{"status":?"alive"}
命令行 uvicorn main:app --host 0.0.0.0 --port 8081 然后訪問(wèn)一下 http://localhost:8081,就會(huì)看到日志輸出,同時(shí)會(huì)保存在 server.log 文件中:

第二種,記錄 uvicorn 的日志
fastapi 其實(shí)是 uvicorn 驅(qū)動(dòng)的,uvicorn 本身就會(huì)在終端輸出信息:
??uvicorn?main:app?--host?0.0.0.0?--port?8081
INFO:?????Started?server?process?[88064]
INFO:?????Waiting?for?application?startup.
INFO:?????Application?startup?complete.
INFO:?????Uvicorn?running?on?http://0.0.0.0:8081?(Press?CTRL+C?to?quit)
將這些信息記錄到文件里就可以了,可以在 fastapi 啟動(dòng)的時(shí)候配置:
@app.on_event("startup")
async?def?startup_event():
????logger?=?logging.getLogger("uvicorn.access")
????handler?=?logging.handlers.RotatingFileHandler("api.log",mode="a",maxBytes?=?100*1024,?backupCount?=?3)
????handler.setFormatter(logging.Formatter("%(asctime)s?-?%(levelname)s?-?%(message)s"))
????logger.addHandler(handler)
這樣,uvicorn 的輸出,就會(huì)記錄在 api.log 中。
第三種,配置 uvicorn 的日志
如果你是這種方法運(yùn)行 FastApi:
app?=?FastAPI()
uvicorn.run(app,?host="0.0.0.0",?port=8000)
那么可以在代碼里配置 uvicorn 的日志,然后在 run 函數(shù)里傳入日志配置信息,就可以了:
log_config?=?uvicorn.config.LOGGING_CONFIG
log_config["formatters"]["access"]["fmt"]?=?"%(asctime)s?-?%(levelname)s?-?%(message)s"
log_config["formatters"]["default"]["fmt"]?=?"%(asctime)s?-?%(levelname)s?-?%(message)s"
uvicorn.run(app,?log_config=log_config)
當(dāng)然,在命令行里面也可以通過(guò) uvicorn --log-config=log.ymal 傳入配置文件:
version: 1
formatters:
simple:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
loggers:
simpleExample:
level: DEBUG
handlers: [console]
propagate: no
root:
level: DEBUG
handlers: [console]
日志文件支持 .ini, .json, .yaml 格式。
最后的話
本文分享了 FastAPI 配置日志的三種方法,后兩種其實(shí)是 uvicorn 配置并記錄日志的方法,如果覺得有幫助,請(qǐng)?jiān)诳?、轉(zhuǎn)發(fā)、評(píng)論,感謝閱讀。
