fastapi uvicorn配置日志

  目前从flask框架转fastapi,之前flask框架日志很好用。这次学习了fastapi的日志使用,第一种是自定义日志,这个不讲了,自己封装就好,第二种是使用uvicorn自带日志。

 

一、配置输出格式化

uvicorn 其实已经有日志,只是没有格式化输出,我们希望可以加点东西丰富输出。

找到 uvicorn.config 里的源码, LOGGING_CONFIG配置如下:

LOGGING_CONFIG: Dict[str, Any] = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "default": {
            "()": "uvicorn.logging.DefaultFormatter",
            "fmt": "%(levelprefix)s %(message)s",
            "use_colors": None,
        },
        "access": {
            "()": "uvicorn.logging.AccessFormatter",
            "fmt": '%(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s',  # noqa: E501
        },
    },
    "handlers": {
        "default": {
            "formatter": "default",
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stderr",
        },
        "access": {
            "formatter": "access",
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stdout",
        },
    },
    "loggers": {
        "uvicorn": {"handlers": ["default"], "level": "INFO", "propagate": False},
        "uvicorn.error": {"level": "INFO"},
        "uvicorn.access": {"handlers": ["access"], "level": "INFO", "propagate": False},
    },
}

这段默认配置我们可以自定义,不过不是改源码,是初始化时加载我们新建的配置。比如在用 uvicorn 启动时,加上参数 log_config,uvicorn 自定义日志配置文件支持 json、yaml、ini 三种格式。

uvicorn.run(app='main:app',host="0.0.0.0",log_config='./uvicorn_config.json',port=8000,loop="asyncio")

以下这段 json 实现了,格式化输出控制台,日志输出到本地文件。首先创建 uvicorn_config.json 存放项目根目录:

{
    "version": 1,
    "disable_existing_loggers": false,
    "formatters": {
        "default": {
            "()": "uvicorn.logging.DefaultFormatter",
            "fmt": "%(asctime)s %(threadName)s %(levelprefix)s  %(message)s",      # 增加了asctime和threadName
            "use_colors": null
        },
        "access": {
            "()": "uvicorn.logging.AccessFormatter",
            "fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(client_addr)s - '%(request_line)s' %(status_code)s"  # 增加了asctime和threadName
        }
    },
    "handlers": {
        "default": {
            "formatter": "default",
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stderr"
        },
        # default日志输出到本地文件,定义了日志路径、备份数量
        "default_file": {
            "formatter": "default",
            "class": "logging.handlers.TimedRotatingFileHandler",
            "filename": "./logs/app.log",
            "when": "midnight",
            "encoding": "utf-8",
            "backupCount": 10
        },
        "access": {
            "formatter": "access",
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stdout"
        },
        # access日志输出到本地文件,定义了日志路径、备份数量
        "access_file": {
            "formatter": "access",
            "class": "logging.handlers.TimedRotatingFileHandler",
            "filename": "./logs/app.log",
            "when": "midnight",
            "encoding": "utf-8",
            "backupCount": 10
                }
    },
    "loggers": {
        # 添加handler,default_file
        "uvicorn": {"handlers": ["default","default_file"], "level": "INFO", "propagate": false},
        "uvicorn.error": {"level": "INFO"},
        # 添加handler,access_file
        "uvicorn.access": {"handlers": ["access","access_file"], "level": "INFO", "propagate": false}
    }
}

 main.py文件

from fastapi import FastAPI
import uvicorn

app = FastAPI()


@app.get("/home")
async def get():
    return {'message':'OK'}

@app.get("/test")
async def get():
    return {'message':'OK'}

@app.get("/dev")
async def get():
    return {'message':'OK'}


if __name__ == "__main__":
    # log_config 加载日志配置
    uvicorn.run(app='main:app',host="0.0.0.0",log_config='./uvicorn_config.json',port=8000,loop="asyncio")

 运行main.py

控制台

app.log

 

二、业务代码调用 uvicorn 日志

查看 uvicorn 日志源码处理机制发现,本质上还是 logger.addHandler 方法添加 handler,所以可以用以下方法调用:

from fastapi import FastAPI
import uvicorn,logging

app = FastAPI()

log = logging.getLogger("uvicorn")


@app.get("/home")
async def get():
    log.info('this is a test')
    return {'message':'OK'}

@app.get("/test")
async def get():
    return {'message':'OK'}

@app.get("/dev")
async def get():
    return {'message':'OK'}


if __name__ == "__main__":
    # log_config 加载日志配置
    uvicorn.run(app='main:app',host="0.0.0.0",log_config='./uvicorn_config.json',port=8000,loop="asyncio")

 输出:

posted @ 2024-07-31 17:30  三只松鼠  阅读(1024)  评论(0编辑  收藏  举报