51Testing软件测试论坛

标题: 为 FastAPI 配置日志的三种方法 [打印本页]

作者: lsekfe    时间: 2022-4-29 09:27
标题: 为 FastAPI 配置日志的三种方法
你好,我是 somenzz,可以叫我征哥,最近在用 FastAPI 的时候,发现 FastAPI 的官方文档没有配置日志的相关说明,今天就分享一下 FastAPI 配置日志的三种方法。
  第一种,就像写脚本那样记录日志
  这一种方法最简单直接,平时写脚本的时候怎么记录日志,这里就怎么记录日志,通常就是先配置日志格式,然后在需要的地方 logger.info 一下:
  配置日志:
  1.   import logging
  2.   logger = logging.getLogger()
  3.   logger.setLevel(logging.INFO)
  4.   ch = logging.StreamHandler()
  5.   fh = logging.FileHandler(filename='./server.log')
  6.   formatter = logging.Formatter(
  7.       "%(asctime)s - %(module)s - %(funcName)s - line:%(lineno)d - %(levelname)s - %(message)s"
  8.   )
  9.   ch.setFormatter(formatter)
  10.   fh.setFormatter(formatter)
  11.   logger.addHandler(ch) #将日志输出至屏幕
  12.   logger.addHandler(fh) #将日志输出至文件
复制代码
如果怕文件太大,可以使用循环日志:

  1.  fh = logging.handlers.RotatingFileHandler("api.log",mode="a",maxBytes = 100*1024, backupCount = 3)
复制代码
然后,在需要记录日志的地方添加 logger.info / logger.warning / logger.debug / logger.error

  1.  from fastapi import FastAPI
  2.   # setup loggers
  3.   import logging
  4.   logger = logging.getLogger()
  5.   logger.setLevel(logging.INFO)
  6.   ch = logging.StreamHandler()
  7.   fh = logging.FileHandler(filename='./server.log'))
  8.   ch.setFormatter(LogFormatter())
  9.   fh.setFormatter(LogFormatter())
  10.   logger.addHandler(ch) #将日志输出至屏幕
  11.   logger.addHandler(fh) #将日志输出至文件
  12.   app = FastAPI()
  13.   @app.get("/")
  14.   async def root():
  15.       logger.info("logging from the root logger")
  16.       return {"status": "alive"}
复制代码


  你可能会说,我接口特别多,难道一行一行加?
  那也不用,你可以在中间件里面拦截所有请求,然后日志记录每一个请求,完整代码如下所示:
  文件名 main.py,重点在 log_requests 函数:
  1.  import logging
  2.   from fastapi import FastAPI
  3.   import time
  4.   import random
  5.   import string
  6.   logger = logging.getLogger()
  7.   logger.setLevel(logging.INFO)
  8.   ch = logging.StreamHandler()
  9.   fh = logging.FileHandler(filename='./server.log')
  10.   formatter = logging.Formatter(
  11.       "%(asctime)s - %(module)s - %(funcName)s - line:%(lineno)d - %(levelname)s - %(message)s"
  12.   )
  13.   ch.setFormatter(formatter)
  14.   fh.setFormatter(formatter)
  15.   logger.addHandler(ch) #将日志输出至屏幕
  16.   logger.addHandler(fh) #将日志输出至文件
  17.   logger = logging.getLogger(__name__)
  18.   app = FastAPI()
  19.   @app.middleware("http")
  20.   async def log_requests(request, call_next):
  21.       idem = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6))
  22.       logger.info(f"rid={idem} start request path={request.url.path}")
  23.       start_time = time.time()
  24.      
  25.       response = await call_next(request)
  26.      
  27.       process_time = (time.time() - start_time) * 1000
  28.       formatted_process_time = '{0:.2f}'.format(process_time)
  29.       logger.info(f"rid={idem} completed_in={formatted_process_time}ms status_code={response.status_code}")
  30.      
  31.       return response
  32.   @app.get("/")
  33.   async def root():
  34.       return {"status": "alive"}
复制代码
命令行 uvicorn main:app --host 0.0.0.0 --port 8081 然后访问一下 http://localhost:8081,就会看到日志输出,同时会保存在 server.log 文件中:
[attach]137728[/attach]
 第二种,记录 uvicorn 的日志
  fastapi 其实是 uvicorn 驱动的,uvicorn 本身就会在终端输出信息:
  1.  > uvicorn main:app --host 0.0.0.0 --port 8081
  2.   INFO:     Started server process [88064]
  3.   INFO:     Waiting for application startup.
  4.   INFO:     Application startup complete.
  5.   INFO:     Uvicorn running on http://0.0.0.0:8081 (Press CTRL+C to quit)
复制代码
 将这些信息记录到文件里就可以了,可以在 fastapi 启动的时候配置:
  1. @app.on_event("startup")
  2.   async def startup_event():
  3.       logger = logging.getLogger("uvicorn.access")
  4.       handler = logging.handlers.RotatingFileHandler("api.log",mode="a",maxBytes = 100*1024, backupCount = 3)
  5.       handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
  6.       logger.addHandler(handler)
复制代码
 这样,uvicorn 的输出,就会记录在 api.log 中。
  第三种,配置 uvicorn 的日志
  如果你是这种方法运行 FastApi:
  1. app = FastAPI()
  2.   uvicorn.run(app, host="0.0.0.0", port=8000)
复制代码
那么可以在代码里配置 uvicorn 的日志,然后在 run 函数里传入日志配置信息,就可以了:
  1.  log_config = uvicorn.config.LOGGING_CONFIG
  2.   log_config["formatters"]["access"]["fmt"] = "%(asctime)s - %(levelname)s - %(message)s"
  3.   log_config["formatters"]["default"]["fmt"] = "%(asctime)s - %(levelname)s - %(message)s"
  4.   uvicorn.run(app, log_config=log_config)
复制代码
当然,在命令行里面也可以通过 uvicorn --log-config=log.ymal 传入配置文件:
  1.  version: 1
  2.   formatters:
  3.     simple:
  4.       format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
  5.   handlers:
  6.     console:
  7.       class: logging.StreamHandler
  8.       level: DEBUG
  9.       formatter: simple
  10.       stream: ext://sys.stdout
  11.   loggers:
  12.     simpleExample:
  13.       level: DEBUG
  14.       handlers: [console]
  15.       propagate: no
  16.   root:
  17.     level: DEBUG
  18.     handlers: [console]
复制代码
日志文件支持 .ini, .json, .yaml 格式。
  最后的话
  本文分享了 FastAPI 配置日志的三种方法,后两种其实是 uvicorn 配置并记录日志的方法。










欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2