如何配置使多模块与API日志统一写入同一日志文件?
问题
我的主程序PGM_A调用API2和子模块Subpgm_1,Subpgm_1会调用SubAPI_1,调用层级如下:
PGM_A -- Subpgm_1 -- SubAPI_1 -- API2
我需要按如下JSON格式写入日志文件:
{"@timestamp":"09/10/2022 11:42:33 AM","log.level":"INFO","message":"Main : Refresh started!!! "}
我已在主程序PGM_A中编写如下代码:
import datetime import logging filename = datetime.now().strftime('Logfile_%H%M%d%m%Y.log') logging.basicConfig(filename=filename, format='{"@timestamp":"%(asctime)s","log.level":"%(levelname)-1s","message":"%(message)s"}', datefmt='%m/%d/%Y %H:%M:%S %p') logger = logging.getLogger('Delta_Refresh_Pipeline') logger.setLevel(logging.INFO) handler = logging.StreamHandler() handler.setLevel(logging.ERROR) logger.addHandler(handler)
目前仅能获取主程序的日志,但需要API和子模块的日志也写入同一个日志文件,最终日志数据应如下所示:
{"@timestamp":"09/10/2022 11:42:33 AM","log.level":"INFO","message":"Log from PGM_A "} {"@timestamp":"09/10/2022 11:42:34 AM","log.level":"INFO","message":"Log from Subpgm_1"} {"@timestamp":"09/10/2022 11:42:35 AM","log.level":"INFO","message":"Log from SubAPI_1"} {"@timestamp":"09/10/2022 11:42:36 AM","log.level":"INFO","message":"Log from API2"} {"@timestamp":"09/10/2022 11:42:37 AM","log.level":"INFO","message":"Log from PGM_A "}
请问需要对API代码和Subpgm_1做哪些修改?
解决方案
Python的logging模块是层级化的,只要子模块和API使用与主程序logger同层级或子层级的logger实例,就能自动继承主程序的日志配置(包括输出文件、格式等)。具体修改如下:
1. 子模块Subpgm_1的修改
在Subpgm_1的代码中,获取主程序logger的子级logger,而非新建独立logger:
import logging # 获取主程序logger的子级logger,名称采用主logger名称+模块名的层级格式 logger = logging.getLogger('Delta_Refresh_Pipeline.Subpgm_1') # 直接使用该logger输出日志 logger.info("Log from Subpgm_1")
2. 子API SubAPI_1的修改
同理,在SubAPI_1中获取Subpgm_1的子级logger,或直接使用主logger的子级:
import logging # 方式1:继承Subpgm_1的logger层级(推荐,更清晰体现调用关系) logger = logging.getLogger('Delta_Refresh_Pipeline.Subpgm_1.SubAPI_1') # 方式2:直接使用主logger的子级(效果一致) # logger = logging.getLogger('Delta_Refresh_Pipeline.SubAPI_1') logger.info("Log from SubAPI_1")
3. API2的修改
在API2中获取主程序logger的子级logger:
import logging logger = logging.getLogger('Delta_Refresh_Pipeline.API2') logger.info("Log from API2")
关键注意事项
- 禁止在子模块或API中再次调用
logging.basicConfig(),否则会覆盖主程序的配置,导致日志输出混乱。 - logger名称用
.分隔表示层级关系,子层级logger会自动继承父层级的所有配置(包括文件handler、日志级别、格式等)。 - 如果子模块需要单独调整日志级别,可对该子logger单独设置,比如
logger.setLevel(logging.DEBUG),不会影响主logger和其他子logger的配置。
内容的提问来源于stack exchange,提问作者usr_lal123
相关产品推荐
相关产品推荐

