不知道大家有沒有想過,為什會在啟動 FastAPI 時,terminal 會出現這些訊息
這其實是因為 uvicorn
預設使用了 logging
模組 (Python 內建的模組),幫我們在特定的時機記錄下這些日誌 (log),包含:啟動 server、收到 API 請求等。
這邊使用的 Log 系統對後端 server 很重要,它幫我們記錄了這個 server 所發生的大小事,可以讓我們查看過去到底做了哪些事情,以及當發生意外時,讓我們可以透過 log 所紀錄的錯誤訊息找出發生問題的原因。
但是,儘管已經有預設的 log 系統,但目前的設定其實不太好用,主要的問題有以下三點:
因此接下來,接下來會開始介紹如何在 FastAPI 加上符合自己需求的 log 系統。
如果想要在 FastAPI 擁有符合自己需求的 log 系統,大方向大概有兩個
今天以介紹第一個做法為主~
在開始之前,讓我們先來看看 logging
這個模組
logging
簡介首先,我們先來看一個範例
# log.py
import logging
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything
這是執行結果
你會發現,logging
跟 print
有點像,它會在 terminal 印出訊息,但以目前的範例程式來看,只有 warning
的才有印出來,info
卻沒有。
這是因為預設的設定是 log level 要 WARNING
等級以上的才會印出來 (可以調整),常見的 log level 有四個,根據嚴重程度由輕到重依序是
完整的可以看這邊
如果要進行設定,可以用 logging.basicConfig()
import logging
logging.basicConfig(filename='example.log', level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
logging.error('And non-ASCII stuff, too, like Øresund and Malmö')
執行後你會發現,terminal 沒有印出訊息了,取而代之的是多了一個 example.log
,內容如下
經過觀察可以發現,它有一個預設模板,會一併紀錄 log level 和 root
,而這個 root
就是預設的 logger (日誌紀錄器) 的名稱。
如果想要改模板,可以用 logging.basicConfig()
的 format
參數
import logging
logging.basicConfig(format='%(asctime)s %(message)s')
logging.warning('is when this event was logged.')
此時就會看到 terminal 樣式變成這樣了
format
內的參數可以參考這邊
在上面的例子中,你會發現你只能在把 log 「存下來」和「顯示在 terminal」兩個做法中選一個,但這其實不是很方便,現實中往往我們會需要這兩個同時都有,或甚至再多加一個把 log 「送到 log server」,這時,我們就可以使用 logger
。
讓我們用 logger
把上面的範例整理在一起
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
ch = logging.StreamHandler()
fh = logging.FileHandler(filename='example.log')
formatter = logging.Formatter("%(asctime)s %(message)s")
ch.setFormatter(formatter)
fh.setFormatter(formatter)
logger.addHandler(ch)
logger.addHandler(fh)
logger.warning('is when this event was logged.')
如此一來,呼叫一次 logger.warning
,就可以同時存在 example.log
中和顯示在 terminal 了,而且都是使用我們自訂的格式
當然,兩邊的格式也可以不相同
這樣做還有一個好處,就是可以把 log 設定獨立到一個檔案,其他地方只要 import 這個設定好的 logger
就好了。
logging
上面有提到,想要在 FastAPI 添加 log 系統的其中一個做法就是直接添加新的 log 設定,因此最簡單的做法如下
# mian.py
from fastapi import FastAPI
import logging
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
app = FastAPI()
@app.get("/")
async def root():
logging.info('Test info log')
return {"message": "Hello World"}
啟動 FastAPI 後,用 Postman 觸發 API 後可以在 terminal 看到我們自訂的 log 訊息 (暫時不用存的,直接顯示在 terminal)
也可以使用 logger
來讓主程式乾淨一些
# mian.py
from fastapi import FastAPI
from log import logger
app = FastAPI()
@app.get("/")
async def root():
logger.info('Test info log')
return {"message": "Hello World"}
# log.py
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
ch = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s %(message)s")
ch.setFormatter(formatter)
logger.addHandler(ch)
今天開啟新的系列 ── log 系統,目前介紹了
明天的內容我要再規劃一下,這次就不先預告了 XD