Как использовать пользовательский OperationId без утечек памяти и игнорирования его в Application Insights?
Мой вопрос:
Как правильно / лучше ввести пользовательский идентификатор корреляции / операции в мой сценарий, который не приводит к утечкам памяти и правильно используется и отображается на портале Azure?
И вот конкретные детали моего сценария:
У меня есть рабочая роль Azure, которая постоянно удаляет сообщения из очереди Azure и выполняет обработку. Сообщение содержит идентификатор корреляции (Operation 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()
толкает мой пользовательский идентификатор корреляции (проверенный с помощью Fiddler) - Application Insights перезаписывает его на портале Azure и отображает свой собственный идентификатор операции, а не мой. Другая телеметрия во время запроса имеет правильный OperationId, который я установил.
Вот фотография утечки памяти после выполнения цикла в течение ~10 минут (растет до 1 ГБ+ через некоторое время):
2 ответа:
Для проблемы утечки памяти - мы нашли первопричину, и мы исправим ее в следующей версии. Однако в вашем примере кода мы рекомендуем не создавать новый канал каждый раз и вместо этого повторно использовать один и тот же канал. Это позволит лучше дозировать и меньше накладных расходов памяти:
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" />
Смотрите также мой пост в блоге о том, как добавить инициализатор телеметрии в глобальный синглтон конфигурация:
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.TelemetryInitializers.Add(new MiTelemetryInitialiser());
Для проблемы идентификатора операции-в последних версиях, в частности для телеметрии запроса, чтобы избежать путаницы между
RequestTelemetry.ID
иTelemetryContext.Operation.ID
(с точки зрения пользовательского интерфейса), мы инициализируемTelemetryContext.Operation.ID
и назначаем то же самоеRequestTelemetry.ID
, как только создается телеметрия запроса. Смотритепример на github . Лучший способ решить эту проблему назначения пользовательского идентификатора операции-принудительно назначить свой идентификатор операции, удалив проверкуstring.IsNullOrEmpty
.