如何使用自定义 OperationId 而不会导致内存泄漏并被 Application Insights 忽略?
How to use a custom OperationId without ending up with memory leaks and it being ignored by Application Insights?
我的问题是:
在我的场景中注入自定义 Correlation/Operation Id 的 correct/better 方法是什么,它不会导致内存泄漏并且在 Azure 门户上正确使用和显示?
下面是我的场景的具体细节:
我有一个 Azure 辅助角色,它不断地从 Azure 队列中取出消息并进行处理。该消息包含一个关联 ID(操作 ID)和操作名称,我希望在处理该消息期间将其用于通过 Application Insights 收集和推送的所有遥测数据。
目前的实现方式是通过自定义 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:
while(!cancellationToken.IsCancellationRequested) {
// 1. Get message from the queue
// 2. Extract operation name and Correlation Id from the message
TelemetryConfiguration config = TelemetryConfiguration.CreateDefault();
var loggingContext = //new logging context with operation name and correlation id
config.TelemetryInitializers.Add(new MiTelemetryInitialiser(loggingContext));
TelemetryClient telemetryClient = new TelemetryClient(config);
// do work
client.Flush();
}
我正在使用这个 TelemetryChannel
:
<TelemetryChannel Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel, Microsoft.AI.ServerTelemetryChannel"/>
有两个问题:
- 内存泄漏(严重)- 我猜是由于
ServerTelemetryChannel
的实现方式(不幸的是,与大多数 .NET SDK 不同——此渠道不是开源的)和紧密循环?
- 尽管
client.TrackRequest()
正在推送我的自定义关联 ID(使用 Fiddler 验证)- Application Insights 正在 Azure 门户上覆盖它并显示它自己的操作 ID 而不是我的。请求期间的其他遥测具有我设置的正确 OperationId。
这是 运行 循环约 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();
}
并将遥测初始化程序添加到 ApplicationInsigths.config
:
<Add Type="Namespace.MiTelemetryInitialiser , AssemblyName" />
另请参阅 my blog post,了解如何将遥测初始化程序添加到全局单例配置:
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.TelemetryInitializers.Add(new MiTelemetryInitialiser());
对于操作id的问题-在最近的版本中,专门针对request telemetry,为了避免混淆RequestTelemetry.ID
和TelemetryContext.Operation.ID
(从UI的角度),我们初始化TelemetryContext.Operation.ID
并在创建请求遥测后立即将其分配给 RequestTelemetry.ID
。参见 example at github。解决分配自定义操作 ID 问题的最佳方法是强制分配您的操作 ID,删除 string.IsNullOrEmpty
检查。
我的问题是:
在我的场景中注入自定义 Correlation/Operation Id 的 correct/better 方法是什么,它不会导致内存泄漏并且在 Azure 门户上正确使用和显示?
下面是我的场景的具体细节:
我有一个 Azure 辅助角色,它不断地从 Azure 队列中取出消息并进行处理。该消息包含一个关联 ID(操作 ID)和操作名称,我希望在处理该消息期间将其用于通过 Application Insights 收集和推送的所有遥测数据。
目前的实现方式是通过自定义 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:
while(!cancellationToken.IsCancellationRequested) {
// 1. Get message from the queue
// 2. Extract operation name and Correlation Id from the message
TelemetryConfiguration config = TelemetryConfiguration.CreateDefault();
var loggingContext = //new logging context with operation name and correlation id
config.TelemetryInitializers.Add(new MiTelemetryInitialiser(loggingContext));
TelemetryClient telemetryClient = new TelemetryClient(config);
// do work
client.Flush();
}
我正在使用这个 TelemetryChannel
:
<TelemetryChannel Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel, Microsoft.AI.ServerTelemetryChannel"/>
有两个问题:
- 内存泄漏(严重)- 我猜是由于
ServerTelemetryChannel
的实现方式(不幸的是,与大多数 .NET SDK 不同——此渠道不是开源的)和紧密循环? - 尽管
client.TrackRequest()
正在推送我的自定义关联 ID(使用 Fiddler 验证)- Application Insights 正在 Azure 门户上覆盖它并显示它自己的操作 ID 而不是我的。请求期间的其他遥测具有我设置的正确 OperationId。
这是 运行 循环约 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();
}
并将遥测初始化程序添加到 ApplicationInsigths.config
:
<Add Type="Namespace.MiTelemetryInitialiser , AssemblyName" />
另请参阅 my blog post,了解如何将遥测初始化程序添加到全局单例配置:
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.TelemetryInitializers.Add(new MiTelemetryInitialiser());
对于操作id的问题-在最近的版本中,专门针对request telemetry,为了避免混淆RequestTelemetry.ID
和TelemetryContext.Operation.ID
(从UI的角度),我们初始化TelemetryContext.Operation.ID
并在创建请求遥测后立即将其分配给 RequestTelemetry.ID
。参见 example at github。解决分配自定义操作 ID 问题的最佳方法是强制分配您的操作 ID,删除 string.IsNullOrEmpty
检查。