You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Functions V4独立模式C#:在ITelemetryInitializer中获取Service Bus消息ConversationID

实现方案

要在Service Bus触发器的所有遥测日志中携带消息的ConversationID,核心是通过AsyncLocal在同一个请求上下文内传递ConversationID——因为ITelemetryInitializer是全局单例,无法直接获取每个请求的消息属性,AsyncLocal可以保证异步上下文内的值隔离,不会出现多请求串值问题。

步骤1:创建请求上下文存储类

这个类用AsyncLocal存储当前请求的ConversationID,作为单例注入到DI容器中,确保每个请求上下文有独立的存储:

public class RequestTelemetryContext
{
    private readonly AsyncLocal<string> _conversationId = new();

    public string? ConversationID
    {
        get => _conversationId.Value;
        set => _conversationId.Value = value;
    }
}

步骤2:更新DI配置

在Program.cs中,保留原有遥测配置的同时,将RequestTelemetryContext注册为单例:

// 原有的遥测配置保留
services.AddSingleton<ITelemetryInitializer, AppSQLInsightsPropertiesTelemetryInitializer>();
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();

// 添加请求上下文存储类
services.AddSingleton<RequestTelemetryContext>();

步骤3:修改ITelemetryInitializer

在初始化器中注入RequestTelemetryContext,从中获取当前请求的ConversationID并添加到遥测属性:

public class AppSQLInsightsPropertiesTelemetryInitializer : ITelemetryInitializer
{
    private readonly RequestTelemetryContext _requestContext;

    // 通过构造函数注入请求上下文
    public AppSQLInsightsPropertiesTelemetryInitializer(RequestTelemetryContext requestContext)
    {
        _requestContext = requestContext;
    }

    public void Initialize(ITelemetry telemetry)
    {
        // 仅当ConversationID存在时添加,避免空值属性
        if (!string.IsNullOrEmpty(_requestContext.ConversationID))
        {
            telemetry.Context.GlobalProperties["ConversationID"] = _requestContext.ConversationID;
        }
    }
}

步骤4:在Service Bus触发器函数中设置ConversationID

在触发器函数里,注入RequestTelemetryContext,读取Service Bus消息的ConversationID并设置到上下文中:

public class ServiceBusTriggerFunction
{
    private readonly RequestTelemetryContext _requestContext;
    private readonly ILogger<ServiceBusTriggerFunction> _logger;

    public ServiceBusTriggerFunction(RequestTelemetryContext requestContext, ILogger<ServiceBusTriggerFunction> logger)
    {
        _requestContext = requestContext;
        _logger = logger;
    }

    [Function("ServiceBusTrigger")]
    public async Task Run(
        [ServiceBusTrigger("your-queue-name", Connection = "ServiceBusConnection")] ServiceBusReceivedMessage message)
    {
        // 读取Service Bus消息自带的ConversationID属性
        var conversationId = message.ConversationId;

        // 设置到请求上下文,供遥测初始化器全局调用
        _requestContext.ConversationID = conversationId;

        // 后续所有日志都会自动携带ConversationID标识
        _logger.LogInformation("Processing message with ConversationID: {ConversationID}", conversationId);

        // 你的业务逻辑代码...
    }
}

关键说明

  • AsyncLocal的上下文隔离特性,确保每个Service Bus消息的处理流程有独立的ConversationID存储,不会被其他请求干扰。
  • RequestTelemetryContext是单例,但AsyncLocal的值是上下文绑定的,无需担心线程安全问题。
  • 初始化器中加入空值判断,避免向遥测属性中添加无效的空字符串。

内容的提问来源于stack exchange,提问作者Maulik Dave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 06:23:21