C# 如何使用自定义OperationId,而不会导致内存泄漏和被应用程序洞察忽略?

C# 如何使用自定义OperationId,而不会导致内存泄漏和被应用程序洞察忽略?,c#,.net,azure,azure-application-insights,C#,.net,Azure,Azure Application Insights,我的问题是: 在我的场景中插入自定义关联/操作Id的正确/更好的方法是什么,它不会导致内存泄漏,并且在Azure门户上正确使用和显示 下面是我的场景的具体细节: 我有一个Azure Worker角色,它不断地将来自Azure队列的消息移出队列并进行处理。该消息包含一个相关Id(操作Id)和操作名称,我希望在处理该消息的过程中,将其用于收集并通过应用程序洞察推送的所有遥测 当前的实现方式是通过一个定制的ITelemetryInitializer,它看起来像这样: public class MiTe

我的问题是:

在我的场景中插入自定义关联/操作Id的正确/更好的方法是什么,它不会导致内存泄漏,并且在Azure门户上正确使用和显示

下面是我的场景的具体细节:

我有一个Azure Worker角色,它不断地将来自Azure队列的消息移出队列并进行处理。该消息包含一个相关Id(操作Id)和操作名称,我希望在处理该消息的过程中,将其用于收集并通过应用程序洞察推送的所有遥测

当前的实现方式是通过一个定制的
ITelemetryInitializer
,它看起来像这样:

public class MiTelemetryInitialiser : ITelemetryInitializer
{
    private readonly ILoggingContext _context;

    public MiTelemetryInitialiser(ILoggingContext context)
    {
        _context = context;
    }

    public void Initialize(ITelemetry telemetry)
    {
        if (string.IsNullOrEmpty(telemetry.Context.Operation.Id) && _context != null)
        {
            telemetry.Context.Operation.Id = _context.OperationId;

            if (!String.IsNullOrWhiteSpace(_context.OperationName))
                telemetry.Context.Operation.Name = _context.OperationName;
        }
    }
}
然后,我的工作者角色处理循环如下所示(si:

我正在使用此
遥测通道

<TelemetryChannel Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel, Microsoft.AI.ServerTelemetryChannel"/>

有两个问题:

  • 内存泄漏(严重)-我猜是由于
    ServerTelemetryChannel
    的实现方式(不幸的是,与大多数.NET SDK不同,此通道不是开源的)和紧密的循环造成的
  • 即使
    client.TrackRequest()
    正在推送我的自定义关联Id(使用Fiddler验证)-Application Insights正在Azure门户上覆盖它,并显示它自己的操作Id,而不是我的操作Id。请求期间的其他遥测具有我设置的正确操作Id
  • 下面是运行循环约10分钟后内存泄漏的照片(一段时间后增长到1GB+):


    对于内存泄漏问题-我们找到了根本原因,将在下一版本中修复。但是,在您的代码示例中,我们建议不要每次创建新通道,而是重复使用同一通道。这将允许更好的批处理和更少的内存开销:

    TelemetryConfiguration config = TelemetryConfiguration.CreateDefault();
    
    var loggingContext = //new logging context with operation name and correlation id
    config.TelemetryInitializers.Add(new MiTelemetryInitialiser(loggingContext));
    
    while(!cancellationToken.IsCancellationRequested) {
        // 1. Get message from the queue
        // 2. Extract operation name and Correlation Id from the message
        TelemetryClient telemetryClient = new TelemetryClient(config);        
    
        // do work
    
        client.Flush();
    }
    
    或者用这个:

    while(!cancellationToken.IsCancellationRequested) {
        // 1. Get message from the queue
        // 2. Extract operation name and Correlation Id from the message
        TelemetryClient telemetryClient = new TelemetryClient();        
    
        // do work
    
        client.Flush();
    }
    
    并将遥测初始值设定项添加到
    applicationInsights.config

    <Add Type="Namespace.MiTelemetryInitialiser , AssemblyName" />
    

    针对操作id问题-在最新版本中,特别是针对请求遥测,以避免在
    RequestTelemetry.id
    TelemetryContext.operation.id
    之间产生混淆(从UI角度),我们初始化
    TelemetryContext.Operation.ID
    ,并在创建请求遥测后立即将其分配给
    RequestTelemetry.ID
    。请参阅。解决分配自定义操作ID问题的最佳方法是强制分配您的操作ID,删除
    string.IsNullOrEmpty
    检查。

    ,除非我错了我无法将
    TelemetryInitializers
    设置移出
    while
    循环,因为我的OperationId来自队列中的消息,因此为了使用正确的OperationId设置依赖项telemetry,我必须在获得OperationId后注入初始值设定项。此外,是否有一个bug可以跟踪以了解是什么en内存泄漏已修复,如果在发行版中修复了内存泄漏?您需要更改遥测初始值设定项,以便它在Initialize方法中获取上下文,而不是在每个操作中创建上下文。遥测客户端和TelementryConfiguration并不打算在每个操作中创建。即使使用内存泄漏修复,也会有显著的执行效果因为每次我们都需要解析配置文件并重新创建一个频道。错误修复应该在3周内随Web SDK 2.0-beta2一起发布。错误修复将在github上完成(我们现在正在移动频道:)@AnastasiaBaranchenkova感谢您的回复!有意义。(对于记录和阅读评论的人-服务器通道的请求如下:)
    <Add Type="Namespace.MiTelemetryInitialiser , AssemblyName" />
    
    Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.TelemetryInitializers.Add(new MiTelemetryInitialiser());