【问题标题】:TelemetryProcessor - Multiple instances overwrite Custom PropertiesTelemetryProcessor - 多个实例覆盖自定义属性
【发布时间】:2019-04-09 18:54:39
【问题描述】:

我有一个非常基本的 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();
    }
}

遥测处理器:

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);
    }
}

【问题讨论】:

    标签: azure-application-insights


    【解决方案1】:

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

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

    TelemetryConfiguration.Active.TelemetryInitializers.Add(new MyTelemetryInitializer());
    

    初始化程序在调用Track..(..)/创建遥测的同一上下文/线程中执行,因此它们将有权访问线程本地存储和/或本地对象以从中读取参数/值。

    【讨论】:

    • 谢谢德米特里。我确实尝试了 Initializer 方法,但看到了相同的行为。也许我完全错过了目标,你能建议另一种方法吗?在上面的代码中,每个 POST 请求都带有它自己的 customPropertyID,它需要显示在与处理该请求相关联的每个 TrackTrace 条目中……例如,somedomain/myApi 标头中带有“CustomProp1”,somedomain/myApi 带有“ CustomProp2”在标题中。对应用洞察的任何跟踪都需要包含 CustomPropertyId,以便可以在门户中对其进行过滤。初始化器是否提供此功能?
    • 如何将ITelemetryProcessor添加到Application_Start
    猜你喜欢
    • 2014-09-19
    • 1970-01-01
    • 2018-05-08
    • 2014-08-18
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 2012-06-02
    • 1970-01-01
    相关资源
    最近更新 更多