如何为Azure Functions中的FastAPI添加调用ID至日志
解决方案:为Azure Functions自定义日志添加Invocation ID
1. 确保正确获取func.Context
首先检查函数入口是否正确声明context参数——这是获取Invocation ID的核心,若未声明则无法拿到对应值。
普通Azure Functions场景
直接在函数主方法中声明context: func.Context参数,读取context.invocation_id并嵌入日志:
import azure.functions as func import logging logger = logging.getLogger(__name__) def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse: # 获取Invocation ID invocation_id = context.invocation_id # 方式1:直接拼接在日志内容中 logger.info(f"[{invocation_id}] 用户发起GET请求") # 方式2:用日志extra参数注入(适合统一格式配置) logger.info("用户发起GET请求", extra={"invocation_id": invocation_id}) return func.HttpResponse(f"请求已处理,Invocation ID: {invocation_id}")
2. FastAPI托管在Azure Functions的场景
若用Azure Functions托管FastAPI应用,需在Function入口将Invocation ID传递给FastAPI请求上下文,再在接口中调用:
步骤1:修改function_app.py传递Invocation ID
import azure.functions as func from fastapi import FastAPI, Request import logging # 初始化FastAPI应用 app = FastAPI() # 配置统一日志格式(强制包含Invocation ID) logger = logging.getLogger(__name__) formatter = logging.Formatter("%(levelname)s | %(invocation_id)s | %(message)s") stream_handler = logging.StreamHandler() stream_handler.setFormatter(formatter) logger.addHandler(stream_handler) logger.setLevel(logging.INFO) # FastAPI接口示例 @app.get("/api/hello") async def hello(request: Request): # 从请求状态中取出Invocation ID invocation_id = request.state.invocation_id # 输出带ID的自定义日志 logger.info("Hello接口被调用", extra={"invocation_id": invocation_id}) return {"message": "Hello World", "invocation_id": invocation_id} # Azure Functions入口函数 def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse: # 将Invocation ID注入FastAPI请求状态 req.state.invocation_id = context.invocation_id # 用AsgiMiddleware处理FastAPI异步请求 return func.AsgiMiddleware(app).handle(req, context)
步骤2:验证日志输出
部署后自定义日志会自动带上Invocation ID,格式示例:
INFO | abc123-def456-ghi789 | Hello接口被调用
该ID与Azure活动日志中的Invocation ID完全一致,可直接在日志聚合器中筛选。
3. 常见问题排查
- 函数入口未声明
context: func.Context参数:这是最常见错误,必须在main方法参数中显式添加。 - FastAPI无法获取
request.state.invocation_id:确保在main函数中已将ID注入req.state,且使用func.AsgiMiddleware(而非WSGIMiddleware,前者支持异步请求状态传递)。 - 日志格式未包含Invocation ID:通过
logging.Formatter配置统一格式,或每条日志手动拼接ID,确保日志聚合器能识别。
内容的提问来源于stack exchange,提问作者Rahul Vasa
相关产品推荐
相关产品推荐

