Google Cloud Logging将Python INFO级自定义日志误识别为ERROR
问题根因
该问题不是日志配置语法错误,是GKE默认日志采集规则与当前日志输出流配置不匹配导致的已知默认行为:
- GKE内置的Cloud Logging采集代理采集容器日志时,默认不会解析非结构化日志文本中打印的级别字段,会直接将所有写入
stderr标准错误流的日志统一标记为ERROR级别,将所有写入stdout标准输出流的日志统一标记为INFO级别。 - 现有配置中仅
uvicorn.access访问日志的handler绑定了stdout流,因此访问日志级别识别正常;其余包括uvicorn主日志、uvicorn.error日志、自定义的jsonrpc/api日志、root日志器全部绑定到输出到stderr的default handler,这些日志器输出的所有内容——哪怕是logger.info()调用产生的INFO级别日志——只要写入stderr流,就会被采集代理统一识别为ERROR。 - 你在应用代码中初始化google-cloud-logging客户端的时机过晚:uvicorn启动时会优先加载通过
--log-config传入的日志配置,完成自定义日志器的handler绑定,后续应用启动阶段执行的client.setup_logging()无法覆盖已经初始化完成的日志器配置,因此没有生效。
修复方案
- 调整日志handler的流绑定规则
将输出INFO等普通级别日志的默认handler从stderr调整为stdout,单独新增一个绑定stderr的错误日志handler,设置该handler仅处理WARNING及以上级别的日志,所有业务和框架日志器同时绑定两个handler即可。修正后的核心配置如下:
{ "version": 1, "disable_existing_loggers": false, "formatters": { "simple": { "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s" }, "default": { "()": "uvicorn.logging.DefaultFormatter", "datefmt": "%Y-%m-%dT%H:%M:%S", "format": "[%(asctime)s.%(msecs)04dZ] %(name)s %(levelprefix)s %(message).400s" }, "access": { "()": "uvicorn.logging.AccessFormatter", "datefmt": "%Y-%m-%dT%H:%M:%S", "format": "[%(asctime)s.%(msecs)04dZ] %(name)s %(levelprefix)s %(message)s" } }, "handlers": { "default": { "formatter": "default", "class": "logging.StreamHandler", "stream": "ext://sys.stdout", "level": "INFO" }, "error": { "formatter": "default", "class": "logging.StreamHandler", "stream": "ext://sys.stderr", "level": "WARNING" }, "access": { "formatter": "access", "class": "logging.StreamHandler", "stream": "ext://sys.stdout" } }, "loggers": { "uvicorn.error": { "level": "INFO", "handlers": ["default", "error"], "propagate": false }, "uvicorn.access": { "level": "INFO", "handlers": ["access"], "propagate": false }, "uvicorn": { "level": "INFO", "handlers": ["default", "error"], "propagate": false }, "jsonrpc": { "level": "INFO", "handlers": ["default", "error"], "propagate": false }, "api": { "level": "INFO", "handlers": ["default", "error"], "propagate": false } }, "root": { "level": "INFO", "handlers": ["default", "error"] } }
- (可选)调整日志客户端初始化逻辑
如果需要更精准的级别识别,可将google-cloud-logging客户端的初始化逻辑提前到uvicorn加载日志配置之前执行,或直接使用SDK提供的结构化日志handler替换原生StreamHandler,输出携带明确严重级别字段的结构化日志,绕过采集代理按输出流判断级别的粗粒度规则。
你之前初步排查的结论完全正确,问题核心就是输出流绑定规则和GKE采集逻辑不匹配,调整后即可恢复正常。
内容的提问来源于stack exchange,提问作者Ingo
相关产品推荐
相关产品推荐

