如何为Python Azure Functions的日志自动添加invocation-id前缀?
解决方案
使用Python标准库原生的logging.LoggerAdapter即可实现需求,完全满足你的两个约束条件:
- 不会修改Azure Functions运行时默认注册的日志处理器、格式化器配置
- 不需要自定义handler/formatter组件,原有Log Analytics数据上报、看板统计逻辑完全不受影响
基础实现代码
适配器定义
import logging from azure import functions as func class InvocationIdAdapter(logging.LoggerAdapter): def process(self, msg, kwargs): return f"({self.extra['invocation_id']}) {msg}", kwargs
函数入口使用示例
def main(msg: func.QueueMessage, ctx: func.Context) -> None: # 基于当前调用上下文初始化适配器 logger = InvocationIdAdapter(logging.getLogger(), {"invocation_id": ctx.invocation_id}) # 后续所有日志调用替换为adapter实例的方法即可,API和原生logging完全兼容 logger.info('entry') logger.info('invocation id of this run: %s', ctx.invocation_id) logger.debug('doing something...') logger.info('exit with success')
多模块场景进阶适配
如果你的函数需要调用其他模块的代码,不想逐层传递logger实例,可以结合contextvars实现全局自动带前缀,无需修改子模块的日志输出逻辑:
import logging from contextvars import ContextVar from azure import functions as func # 全局上下文变量存储当前调用的invocation id invocation_id_var: ContextVar[str] = ContextVar("invocation_id", default="") class GlobalInvocationIdAdapter(logging.LoggerAdapter): def process(self, msg, kwargs): invocation_id = invocation_id_var.get() return f"({invocation_id}) {msg}" if invocation_id else msg, kwargs # 全局初始化一次适配器,所有模块共用 logger = GlobalInvocationIdAdapter(logging.getLogger(), {}) def main(msg: func.QueueMessage, ctx: func.Context) -> None: # 入口处设置invocation id token = invocation_id_var.set(ctx.invocation_id) try: logger.info('entry') # 子模块内直接导入logger使用即可自动携带invocation id前缀 # 例如 from xxx import logger; logger.info("子模块日志") logger.info('exit with success') finally: # 调用结束重置上下文,避免不同调用串扰 invocation_id_var.reset(token)
内容的提问来源于stack exchange,提问作者Kashyap
相关产品推荐
相关产品推荐

