Google Cloud Console日志级别异常:FastAPI+Uvicorn日志级别覆盖问题排查
1. 核心问题定位
你的Uvicorn日志配置替换了Python根日志器的Handler集合,导致google.cloud.logging.Client.setup_logging()添加的CloudLoggingHandler被覆盖。日志只能通过你定义的StreamHandler输出到stdout,而GKE默认会将所有stdout日志标记为INFO级别,忽略实际日志级别。同时,你的日志格式化器只输出%(message)s,丢失了日志级别信息,GCP日志系统无法从日志内容中识别真实级别,进一步加剧了级别显示错误。
2. 具体排查与修复步骤
调整Uvicorn日志配置,保留多Handler
修改uvicorn_log.config,让根日志器同时包含本地控制台Handler和GCP日志Handler,避免替换原有配置:[loggers] keys=root [handlers] keys=console, cloudlogging [formatters] keys=generic [logger_root] level=NOTSET handlers=console, cloudlogging [handler_console] class=StreamHandler formatter=generic args=(sys.stdout,) [handler_cloudlogging] class=google.cloud.logging.handlers.CloudLoggingHandler args=(google.cloud.logging.Client(),) formatter=generic [formatter_generic] format=%(levelname)s: %(message)s修复日志格式化器,保留级别信息
即使只用StreamHandler输出到stdout,也要在格式化器中包含%(levelname)s,让GCP日志系统能通过解析日志内容识别真实级别:[formatter_generic] format=%(levelname)s: %(message)s调整
setup_logging()的调用时机
确保在uvicorn.run()之前调用GCP日志初始化,避免Uvicorn加载配置时覆盖已添加的CloudLoggingHandler:from google.cloud import logging import uvicorn # 先初始化GCP日志 client = logging.Client() client.setup_logging() # 再启动Uvicorn uvicorn.run(app, host="0.0.0.0", port=5021, log_config='uvicorn_log.config')检查根日志器的级别继承
你的[logger_root]设置为NOTSET,意味着根日志器会使用Handler的级别。可在配置中给Handler添加明确级别(如level=DEBUG),确保低级别日志能正常流转:[handler_console] class=StreamHandler formatter=generic args=(sys.stdout,) level=DEBUG [handler_cloudlogging] class=google.cloud.logging.handlers.CloudLoggingHandler args=(google.cloud.logging.Client(),) formatter=generic level=DEBUG
3. 验证方法
修改配置后重新部署,打印不同级别的日志测试:
import logging logging.debug("Debug log") logging.info("Info log") logging.warning("Warning log") logging.error("Error log")
在GCP Console中查看日志的Severity是否与打印级别对应。
内容的提问来源于stack exchange,提问作者SaD

