延續昨天的內容,我們雖然成功的建立了自己的 log,但是我們自訂的 log 和預設的 log 都會顯示在 terminal,造成畫面很亂
謎之音:主辦單位要不要管一下!
因此需要想辦法把預設的關掉,或至少讓它不要在 terminal 印出訊息影響畫面。
logger
... 們?如果想要對 logger
進行操作,我們可以使用昨天用到的 logging.getLogger()
來取得 logger
,只要在括弧內放入 logger
名稱即可。
沒有填的話就是 root logger
但,問題來了,如果我們要操作的是預設的 logger
,我們就需要先取得預設的 logger
的名稱。
好在 loggging
有一個方法可以拿到 logger
名稱清單,那就是 logging.root.manager.loggerDict
這個我在文件中時在找不到哪裡有寫...
讓我們測試一下,用 uvicorn main:app
啟動 main.py
# main.py
from fastapi import FastAPI
import logging
app = FastAPI()
for name in logging.root.manager.loggerDict:
print(name)
在 terminal 可以看到已經有很多 logger 了
此外,也可以發現,預設的 log 需要花一點時間才會印出東西 (因為要等到 uvicorn 啟動完成)。
logger
那在這些 logger
中,到底哪些是我們需要去調整的呢?
在公布答案之前,我們可以先來測試一下 (一樣的做法,啟動 main.py
後,用 Postman 打 API)
# main.py
from fastapi import FastAPI
import logging
app = FastAPI()
logger = logging.getLogger("uvicorn")
logger.handlers = []
@app.get("/")
async def root():
logger.info("Logger Info")
logger.error("Logger Error")
print("Hi")
return {"message": "Hello World"}
結果如下
這邊我們名稱為 uvicorn
的 logger
的 handlers
清空,並用它來手動紀錄 log。
可以發現,現在啟動再也沒有那四行預設的 log 了,但是打 API 一樣有。此外,Info 等級的 log 並沒有在 terminal 顯示出來,只有 Error 才有。
接著稍微調整一下,再試一次
# main.py
from fastapi import FastAPI
import logging
app = FastAPI()
logger = logging.getLogger("uvicorn")
logger.handlers = []
+ logger_ac = logging.getLogger("uvicorn.access")
+ logger_ac.handlers = []
@app.get("/")
async def root():
logger.info("Logger Info")
logger.error("Logger Error")
print("Hi")
return {"message": "Hello World"}
可以發現,現在連打 API 都沒有了。
另外,如果用 uvicorn.access
這個 logger 去紀錄 log (logger_ac.info("Logger access")
),卻會出錯。
這部份程式碼沒放上來,發生錯誤的確切原因我也不太清楚...
所以,根據測試結果,需要額外控制的 logger 至少有兩個,分別是 uvicorn
和 uvicorn.access
。
至於 uvicorn.error
,目前我還不清楚觸發時機,但可以知道的是,它絕對不是設計用來在發生錯誤時觸發的。
uvicorn 有個 issue 就是覺得這個
error
名稱取的並不恰當 XD
logger
不顯示回到最一開始的話題,畫面很亂怎麼辦?
我們只要照上面的方法,將 handlers
清空,再像昨天一樣自己建立自己的 logger 就好,後續使用也是呼叫自己的 logger。
logger
設定並拿來用就好嗎?答案是可以的,既然都可以取得 logger
,那肯定也可以在上面操作,具體的做法可以這樣做
# main.py
from fastapi import FastAPI
from log import init_logging
import logging
app = FastAPI()
logger = init_logging()
logger_ac = logging.getLogger("uvicorn.access")
logger_ac.handlers = []
@app.get("/")
async def root():
logger.info("Logger Info")
logger.error("Logger Error")
print("Hi")
return {"message": "Hello World"}
# log.py
import logging
def init_logging():
logger = logging.getLogger("uvicorn")
logger.handlers = []
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)
return logger
接著再測試一次
可以發現,我們成功修改預設的 logger
了~
除了上面的做法 (取得 logger 後修改設定),還有另一個做法,那就是在用 uvicorn 啟動 FastAPI 時,可以額外代入我們是先設定好的設定檔
uvicorn main:app --log-config=log_conf.yaml
至於 log_conf.yaml
要怎麼寫,文件中有說明,但實在有夠難看懂,因此建議大家去看這個範例,應該會好懂一些。
(好像沒有太多重點可以列,只好換個標題)
今天主要介紹了如何取得預設 logger
並調整它的設定,算是相對進階的主題,希望大家可以看懂 XD