TelemetryProcessor-多个实例覆盖自定义属性

时间:2019-04-09 18:54:40

标签: azure-application-insights

我有一个非常基本的http-POST触发的api,它创建了TelemetryClient。我需要为每个单独的请求在此遥测中提供一个自定义属性,因此我实现了TelemtryProcessor

但是,当处理后续的POST请求并创建新的TelemetryClient时,似乎似乎在干扰第一个请求。我最终在App Insights中看到大约十二个条目,其中包含第一个customPropertyId,第二个条目接近500,而实际上,该数目应该平均分配。似乎第二个TelemetryClient的创建以某种方式干扰了第一个。

下面是基本代码,如果有人对为什么会发生有任何见解(无双关语),我将不胜感激。

处理POST请求的ApiController:

public class TestApiController : ApiController
{
    public HttpResponseMessage Post([FromBody]RequestInput request)
    {
        try
        {
            Task.Run(() => ProcessRequest(request));
            return Request.CreateResponse(HttpStatusCode.OK);
        }
        catch (Exception)
        {
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, Constants.GenericErrorMessage);
        }
    }

    private async void ProcessRequest(RequestInput request)
    {
        string customPropertyId = request.customPropertyId;

        //trace handler creates the TelemetryClient for custom property
        CustomTelemetryProcessor handler = new CustomTelemetryProcessor(customPropertyId);

        //etc.....
    }
}

创建TelemetryClient的CustomTelemetryProcessor:

public class CustomTelemetryProcessor
{
    private readonly string _customPropertyId;
    private readonly TelemetryClient _telemetryClient;

    public CustomTelemetryProcessor(string customPropertyId)
    {
        _customPropertyId = customPropertyId;

        var builder = TelemetryConfiguration.Active.TelemetryProcessorChainBuilder;
        builder.Use((next) => new TelemetryProcessor(next, _customPropertyId));

        builder.Build();

        _telemetryClient = new TelemetryClient();
    }
}

TelemetryProcessor:

public class TelemetryProcessor : ITelemetryProcessor
{
    private string CustomPropertyId { get; }
    private ITelemetryProcessor Next { get; set; }

    // Link processors to each other in a chain.
    public TelemetryProcessor(ITelemetryProcessor next, string customPropertyId)
    {
        CustomPropertyId = customPropertyId;
        Next = next;
    }
    public void Process(ITelemetry item)
    {
        if (!item.Context.Properties.ContainsKey("CustomPropertyId"))
        {
            item.Context.Properties.Add("CustomPropertyId", CustomPropertyId);
        }
        else
        {
            item.Context.Properties["CustomPropertyId"] = CustomPropertyId;
        }

        Next.Process(item);
    }
}

1 个答案:

答案 0 :(得分:1)

最好避免为每个请求创建Telemetry Client,不要重复使用单个静态Telemetry Client实例。遥测处理器和/或遥测初始化程序通常也应该只为遥测管道注册一次,而不是为每个请求注册一次。 TelemetryConfiguration.Active是静态的,通过向每个请求添加新的Processor,只会增加处理器的队列。

适当的设置将是一次将Telemetry Initializer(遥测处理器通常用于过滤,初始化器用于数据丰富)添加到遥测管道中,例如尽管在ApplicationInsights.config文件中添加了一个条目(如果存在),或者通过TelemetryConfiguration.Active上的代码在global.asax中的某个位置添加了条目,例如beta

Application_Start

初始化器是在与调用TelemetryConfiguration.Active.TelemetryInitializers.Add(new MyTelemetryInitializer()); /创建遥测的上下文/线程中执行的,因此它们将可以访问线程本地存储和/或本地对象以从中读取参数/值。