当使用 uvicorn/gunicorn/fastapi 组合时,我相信 access_log_format 选项是 currently ignored。但这主要是为了编辑日志的%(message)s 部分。如果你只是想添加一个时间戳,你应该能够覆盖记录器的行为(尽管默认值对我来说有一个时间戳)。
我在定义 fastapi app 之前将下面的示例放在 __init__.py 中。
import logging, logging.config
LOG_CONFIG = {
"version": 1,
"disable_existing_loggers": True,
"formatters": {"default": {"format": "%(asctime)s [%(process)s] %(levelname)s: %(message)s"}},
"handlers": {
"console": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout",
"level": "INFO",
}
},
"root": {"handlers": ["console"], "level": "INFO"},
"loggers": {
"gunicorn": {"propagate": True},
"gunicorn.access": {"propagate": True},
"gunicorn.error": {"propagate": True},
"uvicorn": {"propagate": True},
"uvicorn.access": {"propagate": True},
"uvicorn.error": {"propagate": True},
},
}
logging.config.dictConfig(LOG_CONFIG)
logger = logging.getLogger(__name__)
查看this 的回答,了解一些关于日志记录 dict 配置的好例子。
如果您真的想编辑 uvicorn 的访问日志格式,我不确定是否有“官方”方法可以这样做。在撰写本文时,它们似乎具有their code 中的硬编码格式:
if self.access_log:
self.access_logger.info(
'%s - "%s %s HTTP/%s" %d',
get_client_addr(self.scope),
self.scope["method"],
get_path_with_query_string(self.scope),
self.scope["http_version"],
status_code,
extra={"status_code": status_code, "scope": self.scope},
)
例如,我有兴趣打印 x-forwarded-for 标头值。一种丑陋的解决方法是修改uvicorn.protocols.utils.get_client_addr 并从传递给它的scope dict 中提取您想要的任何内容。它恰好有请求标头。注意:这可能会产生意想不到的后果,特别是如果 uvicorn 的人将他们的代码更改为使用 get_client_addr 来进行除打印值之外的任何事情。
也许有一种方法可以通过使用自定义记录器的自定义工作类来执行此操作,但我还没有看到这样做。