lsekfe 发表于 2022-4-29 09:27:26

为 FastAPI 配置日志的三种方法

你好,我是 somenzz,可以叫我征哥,最近在用 FastAPI 的时候,发现 FastAPI 的官方文档没有配置日志的相关说明,今天就分享一下 FastAPI 配置日志的三种方法。
  第一种,就像写脚本那样记录日志
  这一种方法最简单直接,平时写脚本的时候怎么记录日志,这里就怎么记录日志,通常就是先配置日志格式,然后在需要的地方 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) #将日志输出至文件
如果怕文件太大,可以使用循环日志:
 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"}

  你可能会说,我接口特别多,难道一行一行加?
  那也不用,你可以在中间件里面拦截所有请求,然后日志记录每一个请求,完整代码如下所示:
  文件名 main.py,重点在 log_requests 函数:
 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 然后访问一下 http://localhost:8081,就会看到日志输出,同时会保存在 server.log 文件中:

 第二种,记录 uvicorn 的日志
  fastapi 其实是 uvicorn 驱动的,uvicorn 本身就会在终端输出信息:
 > uvicorn main:app --host 0.0.0.0 --port 8081
  INFO:   Started server process
  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 启动的时候配置:
@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 的输出,就会记录在 api.log 中。
  第三种,配置 uvicorn 的日志
  如果你是这种方法运行 FastApi:
app = FastAPI()
  uvicorn.run(app, host="0.0.0.0", port=8000)那么可以在代码里配置 uvicorn 的日志,然后在 run 函数里传入日志配置信息,就可以了:
 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)当然,在命令行里面也可以通过 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:
      propagate: no
  root:
  level: DEBUG
  handlers: 日志文件支持 .ini, .json, .yaml 格式。
  最后的话
  本文分享了 FastAPI 配置日志的三种方法,后两种其实是 uvicorn 配置并记录日志的方法。





页: [1]
查看完整版本: 为 FastAPI 配置日志的三种方法