AWS Fargate中Python logging日期重复问题及本地/云端适配
AWS Fargate与本地环境Python日志兼容问题解决
问题背景
我需要让Python应用同时在本地和AWS Fargate运行,本地使用自定义日志格式,Fargate上保留CloudWatch的原生日志格式。当前实现代码如下:
if logging.getLogger().hasHandlers(): log = logging.getLogger() log.setLevel(logging.INFO) else: from logging.handlers import RotatingFileHandler log = logging.getLogger('sm') log.root.setLevel(logging.INFO) # 省略自定义RotatingFileHandler配置代码
问题现象
- CloudWatch日志出现日期重复:
2023-02-08T13:06:27.317+01:00 08/02/2023 12:06 - sm - INFO - Starting
- 本地日志格式正常:
08/02/2023 12:06 - sm - INFO - Starting
原本预期Fargate环境中logging.getLogger().hasHandlers()会返回True,从而复用已有日志配置,但实际未生效,导致自定义格式与CloudWatch默认格式叠加,期望的CloudWatch日志格式为:
2023-02-08T13:06:27.317+01:00 sm - INFO - Starting
问题原因
Fargate的CloudWatch日志采集是通过捕获容器的stdout/stderr实现的,Python的root logger默认并未被添加handler,因此logging.getLogger().hasHandlers()返回False,代码执行了else分支,给日志添加了带日期的自定义格式,而CloudWatch又会为每条捕获的日志自动添加时间戳,最终造成日期重复。
解决方法
通过检查Fargate特有的环境变量AWS_EXECUTION_ENV来区分环境,分别配置日志:
import os import logging from logging.handlers import RotatingFileHandler # 判断是否处于Fargate环境 is_fargate = os.getenv('AWS_EXECUTION_ENV') == 'AWS_ECS_FARGATE' if is_fargate: # Fargate环境:使用root logger,配置无日期的格式,避免与CloudWatch时间戳重复 log = logging.getLogger() log.setLevel(logging.INFO) # 重置已有handler的格式(如果存在) for handler in log.handlers: handler.setFormatter(logging.Formatter('%(name)s - %(levelname)s - %(message)s')) else: # 本地环境:使用自定义日志记录器和文件handler log = logging.getLogger('sm') log.setLevel(logging.INFO) # 禁止日志传播到root logger,避免重复输出 log.propagate = False # 配置文件轮转handler handler = RotatingFileHandler('app.log', maxBytes=10*1024*1024, backupCount=5) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%d/%m/%Y %H:%M') handler.setFormatter(formatter) log.addHandler(handler)
补充说明
- Fargate中,CloudWatch会自动为捕获的每条日志添加时间戳,因此Python日志只需输出内容部分,无需自行添加日期。
- 本地环境设置
log.propagate = False,可以避免日志同时输出到root logger的默认控制台handler,造成重复输出。
内容的提问来源于stack exchange,提问作者rok
相关产品推荐
相关产品推荐

